回顾
今天demo是实现一个异步的计算器,探究redux-saga工作流程
简介
- redux-saga 是一个 redux 的中间件,而中间件的作用是为 redux 提供额外的功能。
- 由于在 reducers 中的所有操作都是同步的并且是纯粹的,即 reducer 都是纯函数,纯函数是指一个函数的返回结果只依赖于它的参数,并且在执行过程中不会对外部产生副作用,即给它传什么,就吐出什么。
- 但是在实际的应用开发中,我们希望做一些异步的(如Ajax请求)且不纯粹的操作(如改变外部的状态),这些在函数式编程范式中被称为“副作用”。
redux-saga 就是用来处理上述副作用(异步任务)的一个中间件。它是一个接收事件,并可能触发新事件的过程管理者,为你的应用管理复杂的流程。
redux-saga工作原理
- 对generator不了解的,看下 阮一峰 generator讲解
- sages 采用 Generator 函数来 yield Effects(包含指令的文本对象)。
- Generator 函数的作用是可以暂停执行,再次执行的时候从上次暂停的地方继续执行
- Effect 是一个简单的对象,该对象包含了一些给 middleware 解释执行的信息。
- 你可以通过使用 effects API 如 fork,call,take,put,cancel 等来创建 Effect。
redux-saga分类
- worker saga 做左右的工作,如调用API,进行异步请求,获取异步封装结果
- watcher saga 监听被dispatch的actions,当接受到action或者知道其被触发时,调用worker执行任务
- root saga 立即启动saga的唯一入口
基本介绍已经讲完了,当做完一个demo后,回头再看 redux-saga官网 或者上面讲解,可能会有更深的体会
使用redux-saga实现一个异步计数器
由于目录结构跟上篇文章一样,在这里就只把变动的部分单独抽离出来讲解
1、修改actions/counter.js
- 增加一个异步记数的动作类型。
import * as Types from "../action-types";
let actions ={
add(num){
return{type:Types.INCREMENT,count:num}
},
minus(num){
return{type:Types.DECREMENT,count:num}
},
//增加了一个异步记数的类型,用于在counter.js中派发动作
async(num){
return {type:Types.ADD_ASYNC}
}
};
export default actions;
复制代码
2、重点,在src目录下增加saga.js文件
//takeEvery=>负责监听 put=>派发动作 call=>告诉saga,执行delay,并传入1000作为参数
import {takeEvery,put,call} from "redux-saga/effects";
import * as Types from "./store/action-types";
const delay = ms=>new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve()
},ms)
})
//saga分为三类 1、rootsaga 2、监听saga 3、worker干活的saga
function* add() {
yield call(delay,1000);
//就是指挥saga中间件向仓库派发动作
yield put({type:Types.INCREMENT,count:10});
}
function* watchAdd() {
//监听派发给仓库的动作,如果动作类型匹配的话,会执行对应的监听生成器
yield takeEvery(Types.ADD_ASYNC,add)
}
export default function* rootSaga() {
yield watchAdd()
}
复制代码
还记得上面说的,rudux-saga分类,root saga ->watcher saga -> worker saga。在这段代码中将会体现,代码我们从上往下看。
2.1 saga工作流程(代码从下往上看)
- 默认导出了rootSaga,即saga的入口文件
- watcher saga ->wactchAdd 负责监听派发的动作,如果动作类型匹配,执行对应的 worker saga
- 上面的worker saga指代的是 add函数
2.2 redux-saga/effects 副作用
在实际的应用开发中,我们希望做一些异步的(如Ajax请求)且不纯粹的操作(如改变外部的状态),这些在函数式编程范式中被称为“副作用”。
- takeEvery=>负责监听,监听派发给仓库的动作,如果动作类型匹配的话,会执行对应的监听生成器->add
- put=>派发动作,可以理解为dispatch
- call=>告诉saga,执行delay函数,并把参数传过去。注意: delay函数必须返回promise
讲到这里,流程就说完了,接下来在store中执行rootSaga