博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Redux和ngrx构建更好的Angular2应用(四)
阅读量:5775 次
发布时间:2019-06-18

本文共 4426 字,大约阅读时间需要 14 分钟。

hot3.png

我的Angular2项目:

原文地址:

调用所有服务

首先,将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
) { 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一直是我在一段时间内感受到的那种“新程序员”的感觉。非常好玩,对不对?? 举个例子,玩弄一下,思考如何在日常项目中使用这种方法。

转载于:https://my.oschina.net/zhongzhong5/blog/903197

你可能感兴趣的文章
layer.js:2 Uncaught TypeError: Cannot read property 'extend' of undefined
查看>>
Centos7.x:开机启动服务的配置和管理
查看>>
HTML5 浏览器返回按钮/手机返回按钮事件监听
查看>>
使用 HPC Pack 为 Azure 中的 Windows HPC 工作负荷创建和管理群集的选项
查看>>
xss
查看>>
iOS:百度长语音识别具体的封装:识别、播放、进度刷新
查看>>
JS获取服务器时间并且计算距离当前指定时间差的函数
查看>>
.NET Core 中依赖注入 AutoMapper 小记
查看>>
Github
查看>>
【C#】C#线程_基元线程的同步构造
查看>>
PyQt5
查看>>
在Android上编译OSG[3.0.2 ] (转)
查看>>
Android Studio rename module Can't rename root module
查看>>
Android应用安全开发之浅谈网页打开APP
查看>>
JS省市区三级联动
查看>>
结构体的定义以及使用
查看>>
[转]CodeSmith和PowerDesigner的使用安装和数据库创建
查看>>
MongoDB - basic
查看>>
RNN以及LSTM的介绍和公式梳理
查看>>
python 线程编程
查看>>