react系列(六)Redux Saga
在Redux中常要管理异步操作,目前社区流行的有Redux-Saga、Redux-thunk等。在管理复杂应用时,推荐使用Redux-Saga,它提供了用 generator 书写类同步代码的能力。
在讲解 ReduxSaga 前,先要说明一下 Redux Middleware 的概念。
Middleware
它提供的是位于 action 被发起之后,到达 reducer 之前的扩展点。
如果写过 Koa 或者 Express ,就会很容易理解 Middleware 的概念。
可以说,Middleware 是一种置于一个调用发起到被处理这段过程之间的函数。它可以对发起的调用进行处理,处理后直接返回,或者调用下一个中间件。
在Redux中,使用柯里化函数声明中间件,一个简单的例子如下:
/**
* 记录所有被发起的 action 以及产生的新的 state。
*/
const logger = store => next => action => {
console.group(action.type)
console.info('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
console.groupEnd(action.type)
return result
}
然后需要将它应用到Redux上
import { createStore, combineReducers, applyMiddleware } from 'redux'
const todoApp = combineReducers(reducers)
const store = createStore(
todoApp,
// applyMiddleware() 告诉 createStore() 如何处理中间件
applyMiddleware(logger, crashReporter)
)
之后dispatch的每一个action都会触发log中间件。
更详细的用法在Redux文档里说明得很详细了,Redux-Middleware。
使用Redux Saga
先定一个小目标,写一个异步增加的demo。
先来创建一个sagas.js文件,用来存放我们的sagas。
import { delay } from 'redux-saga'
import { put, takeEvery } from 'redux-saga/effects'
export function* plusAsync() {
yield delay(1000)
yield put({ type: 'PLUS' })
}
// 在dispatch到store并且匹配pattern的每一个action上派生一个saga
export function* watchPlusAsync() {
yield takeEvery('PLUS_ASYNC', incrementAsync)
}
在上篇例子的基础上,增加一个按钮,用来派发PLUS_ASYNC
事件。
<button onClick={dispatch({type: 'PLUS_ASYNC'}}>{"plusAsync"}</button>
在使用时,经常需要将多个sagas合并成一个。
import { all } from 'redux-saga/effects'
// ...
export default function* rootSaga() {
yield all([
watchPlusAsync()
])
}
最后,需要创建saga Middleware。并将中间件应用到redux上。
import { createStore, applyMiddleware } from "redux";
// ...
// 创建一个Store
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
counter,
applyMiddleware(sagaMiddleware)
)
// 运行sagas
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步。
- 创建
saga
并且将使用takeEvery
给每一个符合pattern
的action
都增加一个对应的saga处理函数。 - 使用
all
导出编写的saga。 - 创建saga中间件,在使用redux创建store时,应用saga中间件。
- 运行中间件。
感谢阅读。
react系列(六)Redux Saga的更多相关文章
- [React] 14 - Redux: Redux Saga
Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga [入门] Ref: 从redux-thun ...
- react native redux saga增加日志功能
redux-logger地址:https://github.com/evgenyrodionov/redux-logger 目前Reac native项目中已经使用redux功能,异步中间件使用red ...
- react系列(五)在React中使用Redux
上一篇展示了Redux的基本使用,可以看到Redux非常简单易用,不限于React,也可以在Angular.Vue等框架中使用,只要需要Redux的设计思想的地方,就可以使用它. 这篇主要讲解在Rea ...
- react系列(四)Redux基本概念和使用
Redux基本概念和使用 先从Flux开始 先放一个Flux官网的链接.需要fq. Flux是Facebook提出的一种构建客户端网页应用的应用架构,它是一种抽象程度很高的设计模式,鼓励单向数据流. ...
- react系列教程
这个系列将从基础语法讲起,把react全家桶都讲到,然后到具体的使用,最后完成后,会写一个完整的demo. 前置要求: 基本的CSS,JS要熟练. 部分ES6语法需要了解.可以参考下面提到的阮一峰老师 ...
- 在React中使用Redux
这是Webpack+React系列配置过程记录的第六篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...
- React 系列教程 1:实现 Animate.css 官网效果
前言 这是 React 系列教程的第一篇,我们将用 React 实现 Animate.css 官网的效果.对于 Animate.css 官网效果是一个非常简单的例子,原代码使用 jQuery 编写,就 ...
- CSS 魔法系列:纯 CSS 绘制各种图形《系列六》
我们的网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. ...
- WCF编程系列(六)以编程方式配置终结点
WCF编程系列(六)以编程方式配置终结点 示例一中我们的宿主程序非常简单:只是简单的实例化了一个ServiceHost对象,然后调用open方法来启动服务.而关于终结点的配置我们都是通过配置文件来 ...
随机推荐
- js中random的应用
1.生成一个随机数 var r = Math.random(); console.info(r); 结果生成一个0-1的随机数(返回0和1之间的伪随机数,可能为0,但总是小于1,[0,1)) 2.生成 ...
- java设计模式-观察者模式学习
最近学习了设计模式中的观察者模式,在这里记录下学习成果. 观察者模式,个人理解:就是一个一对多模型,一个主体做了事情,其余多个主体都可以观察到.只不过这个主体可以决定谁去观察他,以及做什么事情可以给别 ...
- sass判断语句
@if判断 @if可一个条件单独使用,也可以和@else结合多条件使用 scss.style css.style 三目判断 语法为:if($condition, $if_true, $if_false ...
- [转]JSON.parse()和JSON.stringify()
parse用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":&qu ...
- <Android 应用 之路> 百度地图API使用(2)
简介 上一篇只是大致的提一下百度地图API的Android SDK的基本内容,然后抄袭一个官网上的Demo,今天看一下百度地图的第一部分,地图类型和基本的显示. 简单实战 不同类型地图的显示 //设置 ...
- 使用dojo.connect()添加事件的注意事项
使用dojo.connect()添加事件处理器是很方便的,不用再考虑跨浏览器的问题了.但要想正确地使用这个方法,仍然要注意几个问题: 1.用dojo.byId()获取的是dom元素,而用 ...
- 任务十七:零基础JavaScript编码(五)
任务目的 在上一任务基础上继续JavaScript的体验 接触更加复杂的表单对象 实现页面上的一个完整交互功能 用DOM实现一个柱状图图表 任务描述 参考以下示例代码,原始数据包含几个城市的空气质量指 ...
- tableview setData 设置数据(结构体对象)
定义设置的对象类型 Q_DECLARE_METATYPE(LISTITEMDATA *) 设置数据类型 LISTITEMDATA *ptask = &(const_cast<LISTIT ...
- Element和vue框架报错提示
上面报错提示Error in render function: "TypeError:Cannot read property '$options' of undefined" 就 ...
- JS复制DOM元素文字内容
要实现的效果:将HTML页面中的某个DOM元素例如DIV下面的文本内容进行复制. 实现过程如下: <html> <head> <title>Copy text De ...