在Redux中常要管理异步操作,目前社区流行的有Redux-Saga、Redux-thunk等。在管理复杂应用时,推荐使用Redux-Saga,它提供了用 generator 书写类同步代码的能力。

在讲解 ReduxSaga 前,先要说明一下 Redux Middleware 的概念。

Middleware

它提供的是位于 action 被发起之后,到达 reducer 之前的扩展点。

如果写过 Koa 或者 Express ,就会很容易理解 Middleware 的概念。

可以说,Middleware 是一种置于一个调用发起到被处理这段过程之间的函数。它可以对发起的调用进行处理,处理后直接返回,或者调用下一个中间件。

在Redux中,使用柯里化函数声明中间件,一个简单的例子如下:

  1. /**
  2. * 记录所有被发起的 action 以及产生的新的 state。
  3. */
  4. const logger = store => next => action => {
  5. console.group(action.type)
  6. console.info('dispatching', action)
  7. let result = next(action)
  8. console.log('next state', store.getState())
  9. console.groupEnd(action.type)
  10. return result
  11. }

然后需要将它应用到Redux上

  1. import { createStore, combineReducers, applyMiddleware } from 'redux'
  2. const todoApp = combineReducers(reducers)
  3. const store = createStore(
  4. todoApp,
  5. // applyMiddleware() 告诉 createStore() 如何处理中间件
  6. applyMiddleware(logger, crashReporter)
  7. )

之后dispatch的每一个action都会触发log中间件。

更详细的用法在Redux文档里说明得很详细了,Redux-Middleware

使用Redux Saga

先定一个小目标,写一个异步增加的demo。

先来创建一个sagas.js文件,用来存放我们的sagas。

  1. import { delay } from 'redux-saga'
  2. import { put, takeEvery } from 'redux-saga/effects'
  3. export function* plusAsync() {
  4. yield delay(1000)
  5. yield put({ type: 'PLUS' })
  6. }
  7. // 在dispatch到store并且匹配pattern的每一个action上派生一个saga
  8. export function* watchPlusAsync() {
  9. yield takeEvery('PLUS_ASYNC', incrementAsync)
  10. }

在上篇例子的基础上,增加一个按钮,用来派发PLUS_ASYNC事件。

  1. <button onClick={dispatch({type: 'PLUS_ASYNC'}}>{"plusAsync"}</button>

在使用时,经常需要将多个sagas合并成一个。

  1. import { all } from 'redux-saga/effects'
  2. // ...
  3. export default function* rootSaga() {
  4. yield all([
  5. watchPlusAsync()
  6. ])
  7. }

最后,需要创建saga Middleware。并将中间件应用到redux上。

  1. import { createStore, applyMiddleware } from "redux";
  2. // ...
  3. // 创建一个Store
  4. const sagaMiddleware = createSagaMiddleware()
  5. const store = createStore(
  6. counter,
  7. applyMiddleware(sagaMiddleware)
  8. )
  9. // 运行sagas
  10. sagaMiddleware.run(allSagas);

常用API说明

middleware.run(saga, ...args)

动态地运行 saga。只能 用于在 applyMiddleware 阶段 之后 执行 Saga。

takeEvery(pattern, saga, ...args)

在发起(dispatch)到 Store 并且匹配 pattern 的每一个 action 上派生一个 saga。

pattern用来匹配对应的TYPE,对应到指定的saga处理函数上。

args就是相当于指定给saga的参数数组,并且takeEvery会将action拼到最后一个参数上。

takeLatest(pattern, saga, ...args)

在发起到 Store 并且匹配 pattern 的每一个 action 上派生一个 saga。并自动取消之前所有已经启动但仍在执行中的 saga 任务。

这个函数可以说是takeEvery的防抖版本。

具体例子可以查看这里-redux_saga_example

put(action)

创建一个 Effect 描述信息,用来命令 middleware 向 Store 发起一个 action。 这个 effect 是非阻塞型的,并且所有向下游抛出的错误(例如在 reducer 中),都不会冒泡回到 saga 当中。

all

创建一个 Effect 描述信息,用来命令 middleware 并行地运行多个 Effect,并等待它们全部完成。这是与标准的 Promise#all 相当对应的 API。

更多API请查看Saga文档

总结

saga的用法比较简单,分为4步。

  1. 创建saga并且将使用takeEvery给每一个符合patternaction都增加一个对应的saga处理函数。
  2. 使用all导出编写的saga。
  3. 创建saga中间件,在使用redux创建store时,应用saga中间件。
  4. 运行中间件。

感谢阅读。

react系列(六)Redux Saga的更多相关文章

  1. [React] 14 - Redux: Redux Saga

    Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga  [入门] Ref: 从redux-thun ...

  2. react native redux saga增加日志功能

    redux-logger地址:https://github.com/evgenyrodionov/redux-logger 目前Reac native项目中已经使用redux功能,异步中间件使用red ...

  3. react系列(五)在React中使用Redux

    上一篇展示了Redux的基本使用,可以看到Redux非常简单易用,不限于React,也可以在Angular.Vue等框架中使用,只要需要Redux的设计思想的地方,就可以使用它. 这篇主要讲解在Rea ...

  4. react系列(四)Redux基本概念和使用

    Redux基本概念和使用 先从Flux开始 先放一个Flux官网的链接.需要fq. Flux是Facebook提出的一种构建客户端网页应用的应用架构,它是一种抽象程度很高的设计模式,鼓励单向数据流. ...

  5. react系列教程

    这个系列将从基础语法讲起,把react全家桶都讲到,然后到具体的使用,最后完成后,会写一个完整的demo. 前置要求: 基本的CSS,JS要熟练. 部分ES6语法需要了解.可以参考下面提到的阮一峰老师 ...

  6. 在React中使用Redux

    这是Webpack+React系列配置过程记录的第六篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...

  7. React 系列教程 1:实现 Animate.css 官网效果

    前言 这是 React 系列教程的第一篇,我们将用 React 实现 Animate.css 官网的效果.对于 Animate.css 官网效果是一个非常简单的例子,原代码使用 jQuery 编写,就 ...

  8. CSS 魔法系列:纯 CSS 绘制各种图形《系列六》

    我们的网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. ...

  9. WCF编程系列(六)以编程方式配置终结点

    WCF编程系列(六)以编程方式配置终结点   示例一中我们的宿主程序非常简单:只是简单的实例化了一个ServiceHost对象,然后调用open方法来启动服务.而关于终结点的配置我们都是通过配置文件来 ...

随机推荐

  1. js中random的应用

    1.生成一个随机数 var r = Math.random(); console.info(r); 结果生成一个0-1的随机数(返回0和1之间的伪随机数,可能为0,但总是小于1,[0,1)) 2.生成 ...

  2. java设计模式-观察者模式学习

    最近学习了设计模式中的观察者模式,在这里记录下学习成果. 观察者模式,个人理解:就是一个一对多模型,一个主体做了事情,其余多个主体都可以观察到.只不过这个主体可以决定谁去观察他,以及做什么事情可以给别 ...

  3. sass判断语句

    @if判断 @if可一个条件单独使用,也可以和@else结合多条件使用 scss.style css.style 三目判断 语法为:if($condition, $if_true, $if_false ...

  4. [转]JSON.parse()和JSON.stringify()

    parse用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":&qu ...

  5. <Android 应用 之路> 百度地图API使用(2)

    简介 上一篇只是大致的提一下百度地图API的Android SDK的基本内容,然后抄袭一个官网上的Demo,今天看一下百度地图的第一部分,地图类型和基本的显示. 简单实战 不同类型地图的显示 //设置 ...

  6. 使用dojo.connect()添加事件的注意事项

    使用dojo.connect()添加事件处理器是很方便的,不用再考虑跨浏览器的问题了.但要想正确地使用这个方法,仍然要注意几个问题:        1.用dojo.byId()获取的是dom元素,而用 ...

  7. 任务十七:零基础JavaScript编码(五)

    任务目的 在上一任务基础上继续JavaScript的体验 接触更加复杂的表单对象 实现页面上的一个完整交互功能 用DOM实现一个柱状图图表 任务描述 参考以下示例代码,原始数据包含几个城市的空气质量指 ...

  8. tableview setData 设置数据(结构体对象)

    定义设置的对象类型 Q_DECLARE_METATYPE(LISTITEMDATA *) 设置数据类型 LISTITEMDATA *ptask = &(const_cast<LISTIT ...

  9. Element和vue框架报错提示

    上面报错提示Error in render function: "TypeError:Cannot read property '$options' of undefined" 就 ...

  10. JS复制DOM元素文字内容

    要实现的效果:将HTML页面中的某个DOM元素例如DIV下面的文本内容进行复制. 实现过程如下: <html> <head> <title>Copy text De ...