本文共 3887 字,大约阅读时间需要 12 分钟。
今天demo是实现一个异步的计算器,探究redux-saga工作流程
redux-saga 就是用来处理上述副作用(异步任务)的一个中间件。它是一个接收事件,并可能触发新事件的过程管理者,为你的应用管理复杂的流程。
基本介绍已经讲完了,当做完一个demo后,回头再看或者上面讲解,可能会有更深的体会
由于目录结构跟上篇文章一样,在这里就只把变动的部分单独抽离出来讲解
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干活的sagafunction* 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工作流程(代码从下往上看)
2.2 redux-saga/effects 副作用
在实际的应用开发中,我们希望做一些异步的(如Ajax请求)且不纯粹的操作(如改变外部的状态),这些在函数式编程范式中被称为“副作用”。
讲到这里,流程就说完了,接下来在store中执行rootSaga
3、在store/index引入rootSaga
import {createStore,applyMiddleware} from 'redux'; import createSagaMiddleware from "redux-saga"; //引入redux-saga import rootSaga from "../saga" //引入我们上面写好的rootSaga import reducer from "./reducers" let sagaMiddleware =createSagaMiddleware(); //执行得到saga中间件 let store = createStore(reducer,applyMiddleware(sagaMiddleware)); //使用中间件 sagaMiddleware.run(rootSaga); //开始执行rootSaga export default store;复制代码
对于redux中间件没有讲解,这部分内容涉及东西比较多,也不太好理解,写这个react系列目的是尽可能简单的让所有人理解,想看所有的redux源码解析,底部会留下所有总结的代码仓库。
4、在counter.js组件中派发这个异步动作
import React, {Component} from 'react';import ReactDOM from 'react-dom';import {connect} from "react-redux";import actions from "../store/actions/counter"class Counter extends Component { render() { console.log(this.props); return() }}export default connect(state=>({ ...state}),actions)(Counter)复制代码{this.props.number}
//增加异步操作
终结,看效果。可以看出,点击后等待1s才加10。那我们就可以在call()中传入执行的异步函数(如ajax)来获取数据啦。我们这个例对应的delay函数
1、组件中调用了this.props.async(),返回的action对象=>{type:Types.ADD_ASYNC}会在connect方法中被派发
2、saga中takeEvery(Types.ADD_ASYNC,add),监听到动作的类型后,触发 worker saga =>add
3、worker saga中先 yield call(delay,1000); 执行delay方法,延时1s
4、yield put({type:Types.INCREMENT,count:10}); 最后派发的还是INCREMENT的类型
5、接着被reducer处理,更新state
6、页面刷新