使用Redux和ngrx构建更好的Angular2应用(四)

来源:互联网 发布:java常用包介绍 编辑:程序博客网 时间:2024/05/29 05:02

我的Angular2项目:http://git.oschina.net/zt_zhong/CodeBe

原文地址:http://onehungrymind.com/build-better-angular-2-application-redux-ngrx/

调用所有服务

首先,将Http和Headers从angular2/http模块导入到应用中,准备Http调用。

import {Http, Headers} from 'angular2/http';

然后,我们定义一个BASE_URL常量,所以我们只需要键入一次,我们也将创建一个HEADER常量来告诉我们服务器我们如何与它进行通信。这可能不是必需的,这取决于你正在使用的后端,但是要让json-server工作,我不得不添加它。

const BASE_URL = 'http://localhost:3000/items/';const HEADER = { headers: new Headers({ 'Content-Type': 'application/json' }) };

我们修改ItemsService的构造器,将Http对象作为类的一个http属性注入进来。

constructor(private http: Http, private store: Store<AppStore>) {  this.items = store.select('items');}

从这里,让我们修改我们的CRUD方法来处理远程服务器调用,从loadItems开始。我们正在调用this.http.get(BASE_URL)来获取我们的远程items,并且因为Http返回一个observable,所以我们可以通过额外的操作来管理结果。我们将调用map来解析返回结果然后再调用map来创建一个对象然后分发给对应的reducer。map操作的返回结果是一个Observable对象,因为每一个结果都是通过它来操作序列的。为了“捆绑”序列,我们将订阅它,然后通过调度我们的转换结果将控制权交给我们的reducer。

loadItems() {  // Retrieves the items collection, parses the JSON, creates an event with the JSON as a payload,  // and dispatches that event  this.http.get(BASE_URL)    .map(res => res.json())    .map(payload => ({ type: 'ADD_ITEMS', payload }))    .subscribe(action => this.store.dispatch(action));}

当我们更新createItem时,我们将会遵循类似的模式。唯一的不同是,我们使用http.post和格式化了的请求体以及HEADER常量来访问服务器。一旦我们有了返回结果,我们将所有内容映射到我们可以在我们的订阅方法中发送的对象。

createItem(item: Item) {  this.http.post(BASE_URL, JSON.stringify(item), HEADER)    .map(res => res.json())    .map(payload => ({ type: 'CREATE_ITEM', payload }))    .subscribe(action => this.store.dispatch(action));}

更新和删除有点简单,因为我们不依赖于从服务器返回的对象。我们只需要关注操作是否成功。因为这些,我们将使用http.put和http.delete,然后跳过返回结果的映射这一步。我们可以从subscribe中分发一个动作到reducer。看下面的代码:

updateItem(item: Item) {  this.http.put(`${BASE_URL}${item.id}`, JSON.stringify(item), HEADER)    .subscribe(action => this.store.dispatch({ type: 'UPDATE_ITEM', payload: item }));}deleteItem(item: Item) {  this.http.delete(`${BASE_URL}${item.id}`)    .subscribe(action => this.store.dispatch({ type: 'DELETE_ITEM', payload: item }));}

测试

redux的最重要的方面之一是测试reducer是非常容易的,因为它们是具有明确意图的纯函数。关于我们的应用,包含可测试逻辑的表面积已大大减少。当我写这些的时候我并没有想搞笑,但事后看来,那就是!

配置

我不会进入整个测试工具,而是快速浏览我们的测试规范。我们需要做的第一步是导入items和selectedItems以及从angular2/testing中导入it,describe和expect。稍等。这不是Jasmine的方法吗??是的,Angular2默认使用的就是Jasmine。

import {items, selectedItem} from './items';import {  it,  describe,  expect} from 'angular2/testing';

作为参考,我们的规格的骨架看起来像这样。

describe('Items', () => {  describe('selectedItem store', () => {    it('returns null by default', () => {});    it('SELECT_ITEM returns the provided payload', () => {});  });  describe('items store', () => {    let initialState = [      { id: 0, name: 'First Item' },      { id: 1, name: 'Second Item' }    ];    it('returns an empty array by default', () => {});    it('ADD_ITEMS', () => {});    it('CREATE_ITEM', () => {});    it('UPDATE_ITEM', () => {});    it('DELETE_ITEM', () => {});  });});

测试真的很容易写,因为我们从一个初始状态开始,当我们向我们的reducer发送一个动作时,我们知道我们应该得到什么。我们知道,如果我们发出ADD_ITEMS的动作,我们将收回我们在有效载荷(payload)中的任何内容,我们在下面的断言中看到。

it('ADD_ITEMS', () => {  let payload = initialState,      stateItems = items([], {type: 'ADD_ITEMS', payload: payload}); // Don't forget to include an initial stateexpect(stateItems).toEqual(payload);});

如果我们使用CREATE_ITEM的动作类型调用items reducer,那么我们预期结果将是初始数组加上新的记录。

it('CREATE_ITEM', () => {  let payload = {id: 2, name: 'added item'},      result = [...initialState, payload],      stateItems = items(initialState, {type: 'CREATE_ITEM', payload: payload});expect(stateItems).toEqual(result);});

我们可以轻松地阐述剩下的两个reducer的方法的预期结果,然后为我们写下如下所示的断言。

it('UPDATE_ITEM', () => {  let payload = { id: 1, name: 'Updated Item' },      result = [ initialState[0], { id: 1, name: 'Updated Item' } ],      stateItems = items(initialState, {type: 'UPDATE_ITEM', payload: payload});expect(stateItems).toEqual(result);});it('DELETE_ITEM', () => {  let payload = { id: 0 },      result = [ initialState[1] ],      stateItems = items(initialState, {type: 'DELETE_ITEM', payload: payload});expect(stateItems).toEqual(result);});

回顾

我们已经在本文中讲了很多,如果你已经做到了这一点! 让我们快速回顾一下我们所做的工作。

  1. redux的核心特性是统一的状态,事件向上以及自顶向下的状态流。
  2. @ngrx/store实现使用observables可以让我们使用异步管道填充我们的模板。
    3.我们创建了reducers,它接收一个动作和一个状态,并且返回一个新的状态对象。
    4.我们的reducer功能必须是纯粹的,所以我们看到了如何创建它们而不会使我们的集合改变。
    5.一个store是一个基本的键值对map,和一些处理事件和发射状态的机制。
    6.通过使用store.emit来广播事件。
    7.我们使用store.select来订阅数据。
    8.使用表单创建本地副本以避免更高级别的改变。
    9.使用异步调用,我们通过Observable序列传递我们的结果,然后在完成时将该事件发送到reducer。
    10.reducer非常易于测试,因为方法非常纯净。

通过@ngrx/store学习redux一直是我在一段时间内感受到的那种“新程序员”的感觉。非常好玩,对不对??
举个例子,玩弄一下,思考如何在日常项目中使用这种方法。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果7网速太慢怎么办 ps中图片选不中怎么办 加装硬盘不显示怎么办 win10网络无权限访问怎么办 电脑装机时c盘隐藏怎么办 word不允许修改锁定了是怎么办 word文档只读不能编辑怎么办 word无法读取文档时怎么办 ps超出2g存不了怎么办 qq帐号不记得了怎么办 苹果手机wifi密码输错怎么办 qq搜索关键字屏蔽了怎么办 手机数据被屏蔽了怎么办 ea账号安全问题答案忘了怎么办 电脑用户账户密码忘记了怎么办 公司名字审核通过剩下怎么办 抖音一直在审核怎么办 平板电脑显示ipad已停用怎么办 违章车型与实际车型不符怎么办 网购与实物不符怎么办 内网ip地址丢失怎么办 转账户名写错了怎么办 工资卡开户写错公司名称怎么办 商标跟别人重了怎么办 不受信任的应用打不开怎么办 oppo手机安全证书过期怎么办 网站安全证书有问题怎么办 公章圆圈摔坏了怎么办 高风险办税人员怎么办 公司因担保被起诉怎么办 借公司钱被起诉怎么办 qq群管理员满了怎么办 微信公众号搜索不到怎么办 微信名字改不了怎么办 微信号第一次限制登录怎么办 微信第一次限制登录怎么办 老板不回我微信怎么办 微信号换手机号了怎么办 电话被对方拉黑怎么办 微信被好友拉黑了怎么办 微信收藏删了怎么办