今天demo是實現一個異步的計算器,探究redux-saga工做流程html
redux-saga 就是用來處理上述反作用(異步任務)的一箇中間件。它是一個接收事件,並可能觸發新事件的過程管理者,爲你的應用管理複雜的流程。react
基本介紹已經講完了,當作完一個demo後,回頭再看redux-saga官網或者上面講解,可能會有更深的體會git
因爲目錄結構跟上篇文章同樣,在這裏就只把變更的部分單獨抽離出來說解github
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;
複製代碼
//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分爲三類 一、rootsaga 二、監聽saga 三、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。在這段代碼中將會體現,代碼咱們從上往下看。ajax
在實際的應用開發中,咱們但願作一些異步的(如Ajax請求)且不純粹的操做(如改變外部的狀態),這些在函數式編程範式中被稱爲「反作用」。編程
講到這裏,流程就說完了,接下來在store中執行rootSagaredux
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源碼解析,底部會留下全部總結的代碼倉庫。promise
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(
<div>
<h1>{this.props.number}</h1>
<button onClick={()=>{this.props.add(5)}}>+</button>
<button onClick={()=>{this.props.minus(1)}}>-</button>
//增長異步操做
<button onClick={()=>{this.props.async()}}>異步加10</button>
</div>
)
}
}
export default connect(state=>({
...state
}),actions)(Counter)
複製代碼
終結,看效果。能夠看出,點擊後等待1s才加10。那咱們就能夠在call()中傳入執行的異步函數(如ajax)來獲取數據啦。咱們這個例對應的delay函數bash
一、組件中調用了this.props.async(),返回的action對象=>{type:Types.ADD_ASYNC}會在connect方法中被派發app
二、saga中takeEvery(Types.ADD_ASYNC,add),監聽到動做的類型後,觸發 worker saga =>add
三、worker saga中先 yield call(delay,1000); 執行delay方法,延時1s
四、yield put({type:Types.INCREMENT,count:10}); 最後派發的仍是INCREMENT的類型
五、接着被reducer處理,更新state
六、頁面刷新