初识react(四) react中异步解决方案之 redux-saga
回顧
- 初識react(一) 揭開jsx語法和虛擬DOM面紗
- 初識react(二) 實現(xiàn)一個簡版的html redux.js的demo
- 初識react(三)在 react中使用redux來實現(xiàn)簡版計數(shù)器
- 初識react(四) react中異步解決方案之 redux-saga
- 初識react(五) 數(shù)據(jù)流終極解決方案 dva(零配置)
今天demo是實現(xiàn)一個異步的計算器,探究redux-saga工作流程
簡介
- redux-saga 是一個 redux 的中間件,而中間件的作用是為 redux 提供額外的功能。
- 由于在 reducers 中的所有操作都是同步的并且是純粹的,即 reducer 都是純函數(shù),純函數(shù)是指一個函數(shù)的返回結(jié)果只依賴于它的參數(shù),并且在執(zhí)行過程中不會對外部產(chǎn)生副作用,即給它傳什么,就吐出什么。
- 但是在實際的應(yīng)用開發(fā)中,我們希望做一些異步的(如Ajax請求)且不純粹的操作(如改變外部的狀態(tài)),這些在函數(shù)式編程范式中被稱為“副作用”。
redux-saga 就是用來處理上述副作用(異步任務(wù))的一個中間件。它是一個接收事件,并可能觸發(fā)新事件的過程管理者,為你的應(yīng)用管理復(fù)雜的流程。
redux-saga工作原理
- 對generator不了解的,看下阮一峰 generator講解
- sages 采用 Generator 函數(shù)來 yield Effects(包含指令的文本對象)。
- Generator 函數(shù)的作用是可以暫停執(zhí)行,再次執(zhí)行的時候從上次暫停的地方繼續(xù)執(zhí)行
- Effect 是一個簡單的對象,該對象包含了一些給 middleware 解釋執(zhí)行的信息。
- 你可以通過使用 effects API 如 fork,call,take,put,cancel 等來創(chuàng)建 Effect。
redux-saga分類
- worker saga 做左右的工作,如調(diào)用API,進行異步請求,獲取異步封裝結(jié)果
- watcher saga 監(jiān)聽被dispatch的actions,當(dāng)接受到action或者知道其被觸發(fā)時,調(diào)用worker執(zhí)行任務(wù)
- root saga 立即啟動saga的唯一入口
基本介紹已經(jīng)講完了,當(dāng)做完一個demo后,回頭再看redux-saga官網(wǎng)或者上面講解,可能會有更深的體會
使用redux-saga實現(xiàn)一個異步計數(shù)器
由于目錄結(jié)構(gòu)跟上篇文章一樣,在這里就只把變動的部分單獨抽離出來講解
- 先回顧下初識react(三)在 react中使用redux來實現(xiàn)簡版計數(shù)器
1、修改actions/counter.js
- 增加一個異步記數(shù)的動作類型。
2、重點,在src目錄下增加saga.js文件
//takeEvery=>負責(zé)監(jiān)聽 put=>派發(fā)動作 call=>告訴saga,執(zhí)行delay,并傳入1000作為參數(shù) 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、監(jiān)聽saga 3、worker干活的saga function* add() {yield call(delay,1000);//就是指揮saga中間件向倉庫派發(fā)動作yield put({type:Types.INCREMENT,count:10}); } function* watchAdd() {//監(jiān)聽派發(fā)給倉庫的動作,如果動作類型匹配的話,會執(zhí)行對應(yīng)的監(jiān)聽生成器yield takeEvery(Types.ADD_ASYNC,add) } export default function* rootSaga() {yield watchAdd()}還記得上面說的,rudux-saga分類,root saga ->watcher saga -> worker saga。在這段代碼中將會體現(xiàn),代碼我們從上往下看。
2.1 saga工作流程(代碼從下往上看)
- 默認導(dǎo)出了rootSaga,即saga的入口文件
- watcher saga ->wactchAdd 負責(zé)監(jiān)聽派發(fā)的動作,如果動作類型匹配,執(zhí)行對應(yīng)的 worker saga
- 上面的worker saga指代的是 add函數(shù)
2.2 redux-saga/effects 副作用
在實際的應(yīng)用開發(fā)中,我們希望做一些異步的(如Ajax請求)且不純粹的操作(如改變外部的狀態(tài)),這些在函數(shù)式編程范式中被稱為“副作用”。
- takeEvery=>負責(zé)監(jiān)聽,監(jiān)聽派發(fā)給倉庫的動作,如果動作類型匹配的話,會執(zhí)行對應(yīng)的監(jiān)聽生成器->add
- put=>派發(fā)動作,可以理解為dispatch
- call=>告訴saga,執(zhí)行delay函數(shù),并把參數(shù)傳過去。注意: delay函數(shù)必須返回promise
講到這里,流程就說完了,接下來在store中執(zhí)行rootSaga
3、在store/index引入rootSaga
import {createStore,applyMiddleware} from 'redux';import createSagaMiddleware from "redux-saga"; //引入redux-sagaimport rootSaga from "../saga" //引入我們上面寫好的rootSagaimport reducer from "./reducers"let sagaMiddleware =createSagaMiddleware(); //執(zhí)行得到saga中間件let store = createStore(reducer,applyMiddleware(sagaMiddleware)); //使用中間件sagaMiddleware.run(rootSaga); //開始執(zhí)行rootSagaexport default store;對于redux中間件沒有講解,這部分內(nèi)容涉及東西比較多,也不太好理解,寫這個react系列目的是盡可能簡單的讓所有人理解,想看所有的redux源碼解析,底部會留下所有總結(jié)的代碼倉庫。
4、在counter.js組件中派發(fā)這個異步動作
- 代碼跟上篇文章一模一樣,只是增加了按鈕實現(xiàn)異步操作
終結(jié),看效果。可以看出,點擊后等待1s才加10。那我們就可以在call()中傳入執(zhí)行的異步函數(shù)(如ajax)來獲取數(shù)據(jù)啦。我們這個例對應(yīng)的delay函數(shù)
最后在梳理下整個過程
-
1、組件中調(diào)用了this.props.async(),返回的action對象=>{type:Types.ADD_ASYNC}會在connect方法中被派發(fā)
-
2、saga中takeEvery(Types.ADD_ASYNC,add),監(jiān)聽到動作的類型后,觸發(fā) worker saga =>add
-
3、worker saga中先 yield call(delay,1000); 執(zhí)行delay方法,延時1s
-
4、yield put({type:Types.INCREMENT,count:10}); 最后派發(fā)的還是INCREMENT的類型
-
5、接著被reducer處理,更新state
-
6、頁面刷新
-
更多優(yōu)質(zhì)文章參考
-
redux所有源碼解析戳這里
總結(jié)
以上是生活随笔為你收集整理的初识react(四) react中异步解决方案之 redux-saga的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个vue加egg.js的博客
- 下一篇: WePY:在质疑中前进 | 文末福利