首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 Redux 实现异步操作-6

使用 Redux 实现异步操作-6

回顾一下我刚才的操作:
我实现了一个抓取操作创建器,它返回一个函数,而不是像大部分操作创建器一样返回一个对象。该函数使用 Google Books API        异步抓取图书,并在异步抓取的各个阶段,通过使用操作创建器创建操作并使用 Redux dispatch() 函数分派操作来分派其他操作。
抓取操作由抓取缩减程序处理。当抓取开始时,抓取缩减程序返回的状态是一个空数组。当抓取成功时,抓取缩减程序返回抓取的图书。如果抓取失败,抓取缩减程序会将状态重置为空数组。
但是,这里存在一个问题。默认情况下,Redux 仅支持对象形式的操作,不支持函数形式的操作。如果您尝试运行本节中的代码,则会看到一个错误:
Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.




因为 Redux 不支持函数形式的操作,所以我需要指导它支持这类操作 — 通过实现 Redux 中间件。
Redux 中间件我们知道,要使用 Redux 更改应用程序状态,则需要分派操作。为了响应操作分派,Redux 会调用应用程序的缩减程序,将当前状态和操作发送给它。该缩减程序随后返回新状态。
我们还知道,默认情况下,操作必须是纯 JavaScript        对象;它们不能是函数。但是对于异步操作,如果可以将异步操作指定为函数(就像我在上一节中所做的那样),则会非常方便。
幸运的是,Redux 在分派操作和调用缩减程序之间提供了一个挂钩。这个挂钩称为中间件,只需调用 Redux 的          applyMiddleware() 函数即可应用它。
回想一下 ,applyMiddleware() 是 5 个顶级 Redux 函数之一。可使用          applyMiddleware() 通过拦截分派调用的第三方中间件来扩展        Redux。在您处理任务的主要执行工作之前,可以使用此工具实现许多类型的横切关注点,例如日志记录、身份验证、授权或性能指标集合。
我首先将展示如何在图书搜索应用程序中使用现有的有帮助的中间件,然后展示如何创建您自己的中间件。
使用 Redux 中间件创建 Redux 存储时,可通过 Redux applyMiddleware() 函数应用 Redux 中间件。清单 14 展示了如何将         中间件用于图书搜索应用程序。
清单 14. 使用            redux-thunk        (store.js)
1
2
3
4
5
import { createStore, applyMiddleware } from 'redux'
import { reducers } from './reducers'
import thunk from 'redux-thunk'

export const store = createStore(reducers, applyMiddleware(thunk))




redux-thunk 中间件刚好可以满足我在图书搜索应用程序中的需求 — 除了纯 JavaScript        对象外,还要将操作实现为函数。您可以使用 npm install redux-thunk 安装它。
从清单 14 中可以看到,Redux 中间件很容易使用。现在我将展示如何实现您自己的中间件。
实现中间件在清单 15 中,我将 redux-thunk 替换为自定义中间件。
清单 15. 使用自定义中间件          (store.js)        
1
2
3
4
5
import { createStore, applyMiddleware } from 'redux'
import { reducers } from './reducers'
import { thunk } from './middleware'

export const store = createStore(reducers, applyMiddleware(thunk))




清单 16 展示了这个自定义中间件的实现。
清单 16. Thunk 中间件          (middleware.js)
1
2
3
4
5
6
7
8
9
10
11
12
export function thunk(store) {
  return function(dispatch) {
    return function(action) {
      if(typeof action === 'function') {
        action(dispatch, store.getState) // invoke the action
      }
      else {
        return dispatch(action) // dispatch normally
      }
    }
  }
}




Redux 中间件(例如清单 16 中的 thunk)是一个 JavaScript          函数。更具体地讲,它是一个返回一个函数的函数,返回的函数又会返回一个函数。您绝不会直接调用 Redux          中间件,但是如果您要这么做,以下是实现方法:thunk(store)(dispatch)(action)。
箭头函数会让实现看起来更美观,但不一定更容易理解。清单 17 给出了使用箭头函数重写的  的代码。
清单 17. 使用箭头函数的 Thunk          中间件        (middleware.js)
1
2
3
4
5
6
7
8
export const thunk = store => dispatch => action => {
  if(typeof action === 'function') {
    action(dispatch, store.getState) // invoke the action
  }
  else {
    return dispatch(action) // dispatch normally
  }
}




无论是否使用箭头函数,要实现 Redux 中间件,必须实现一个返回一个函数的函数,而且返回的函数还要返回另一个函数。简单地看看此 recipe,其中            NAME 表示您的中间件的名称,... 是代码:
const NAME = store ⇒ dispatch ⇒ action ⇒ { ...}
现在您已经了解了实现 Redux 中间件的基本原理,让我们来看看  中的 thunk        中间件的实现。得益于 JavaScript 闭包的魔力,中间件函数能够访问 store(Redux        存储)、dispatch(Redux dispatch() 函数)和        action(您即将分派的操作)。
thunk 中间件会检查该操作是否是函数;如果是,thunk 会调用该操作,传递 dispatch        函数和存储的 getState() 函数。如果该操作不是函数,thunk 中间件会按照 Redux 的正常方式处理操作        — 调用 dispatch() 函数并传递该操作。
结束语获取源代码
可从 GitHub 上的           获取该应用程序的完整源代码。

Redux 应用程序通过 Redux dispatch() 函数分派操作来更改状态。顾名思义,dispatch()        函数将操作分派给应用程序的缩减程序,缩减程序创建一个新应用程序状态。在本期文章中,您了解了如何利用该生命周期,通过实现 Redux 中间件来扩展 Redux 的工作能力,中间件使        Redux 能够处理函数形式的操作,是所有异步操作的一个便捷工具。
返回列表