React Native Redux Typescript使用 redux-thunk or redux-saga

Redux 的核心理念是嚴(yán)格的單向數(shù)據(jù)流馅袁,只能通過 dispatch(action) 的方式修改 store昔馋,流程如下:

view ->? action -> reducer -> store

但是在業(yè)務(wù)復(fù)雜的以及和api數(shù)據(jù)對接的過程中肯定會遇到大量的異步操作蜓谋。我們?nèi)绾蝸斫鉀Q這些場景呢富俄?

redux中間件

什么是redux中間件

redux中間件

這里我們先從redux的中間件說起呕臂, 中間件拾稳,顧名思義:進行中間處理的物件。類似于面向?qū)ο缶幊痰腁OP編程思想(不了解AOP的可以忽略這句話)

簡單的說:中間件可以控制在store dispatch action之前和之后的業(yè)務(wù)邏輯曲秉。也就是說 中間件實現(xiàn)了改寫 store.dispatch 方法實現(xiàn)了action -> reducer的攔截的行為采蚀。

如果我們分別注冊三個中間件: 中間件A 中間件B 中間件C

那么

中間件A -> 中間件B-> 中間件C-> 原始 dispatch -> 中間件C -> 中間件B -> 中間件A

和異步處理的關(guān)系

綜上所述:中間件可以領(lǐng)過的改變 dispatch的時機,這樣我們就可以很方便的處理異步場景了承二。

因此各種 redux異步處理中間件應(yīng)運而生榆鼠。比較知名的有redux-thunk和redux-saga。

redux-thunk

redux-thunk中間件可以讓action創(chuàng)建函數(shù)先不返回一個action對象亥鸠,而是返回一個函數(shù)妆够,函數(shù)傳遞兩個參數(shù)(dispatch,getState),在函數(shù)體內(nèi)進行業(yè)務(wù)邏輯的封裝

functionadd(){return{type:'ADD',? ? }}functionaddIfOdd(){return(dispatch, getState) =>{constcurrentValue = getState();if(currentValue %2==0) {returnfalse;? ? ? ? }//分發(fā)一個任務(wù)dispatch(add())? ? }}

詳細(xì)代碼可以查看分支:https://github.com/YahuiWong/react-native-typescript/tree/redux-thunk

redux-saga

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 API 參考)

如 yield call(fetch, '/products') 即 yield 了下面的對象,call 創(chuàng)建了一條描述結(jié)果的信息庸疾,然后乍楚,redux-saga middleware 將確保執(zhí)行這些指令并將指令的結(jié)果返回給 Generator:

// Effect -> 調(diào)用 fetch 函數(shù)并傳遞 `./products` 作為參數(shù){type: CALL,function: fetch,? args: ['./products']}

與 redux-thunk 不同的是,在 redux-saga 中届慈,UI 組件自身從來不會觸發(fā)任務(wù)徒溪,它們總是會 dispatch 一個 action 來通知在 UI 中哪些地方發(fā)生了改變,而不需要對 action 進行修改金顿。redux-saga 將異步任務(wù)進行了集中處理臊泌,且方便測試。

dispacth({ type: 'FETCH_REQUEST', url: /* ... */} );

所有的東西都必須被封裝在 sagas 中串绩。sagas 包含3個部分缺虐,用于聯(lián)合執(zhí)行任務(wù):

worker saga

做所有的工作,如調(diào)用 API礁凡,進行異步請求高氮,并且獲得返回結(jié)果

watcher saga

監(jiān)聽被 dispatch 的 actions,當(dāng)接收到 action 或者知道其被觸發(fā)時顷牌,調(diào)用 worker saga 執(zhí)行任務(wù)

root saga

立即啟動 sagas 的唯一入口

? 如何使用剪芍?

首先,我們得在文件入口中加入 saga 中間件窟蓝,并且啟動它罪裹,它會一直運行:

//...import{ createStore, applyMiddleware}from'redux';importcreateSagaMiddlewarefrom'redux-saga';importappReducerfrom'./reducers';importrootSagafrom'./saga';//...constsagaMiddleware = createSagaMiddleware()conststore=createStore(rootReducer,applyMiddleware(sagaMiddleware));sagaMiddleware.run(rootSaga)render(,document.getElementById('app'));

然后,就可以在 sagas 文件夾中集中寫 saga 文件了:

import{delay}from'redux-saga';import{put,takeEvery,all}from'redux-saga/effects';import{ADD}from'./actionsTypes';function*addSync(){yielddelay(1000);yieldput({type:ADD})}function*watchaddSync(){yieldtakeEvery("addSync",addSync)}exportdefaultfunction*rootSaga(){yieldall([? ? ? ? watchaddSync()? ? ])}

在 redux-saga 中的基本概念就是:sagas 自身不真正執(zhí)行副作用(如函數(shù) call)运挫,但是會構(gòu)造一個需要執(zhí)行作用的描述状共。中間件會執(zhí)行該副作用并把結(jié)果返回給 generator 函數(shù)。

對上述例子的說明:

(1)引入的 redux-saga/effects 都是純函數(shù)谁帕,每個函數(shù)構(gòu)造一個特殊的對象峡继,其中包含著中間件需要執(zhí)行的指令,如:call(fetchUrl, url) 返回一個類似于 {type: CALL, function: fetchUrl, args: [url]} 的對象匈挖。

(2)在 watcher saga watchFetchRequests中:

首先 yield take('FETCH_REQUEST') 來告訴中間件我們正在等待一個類型為 FETCH_REQUEST 的 action碾牌,然后中間件會暫停執(zhí)行 wacthFetchRequests generator 函數(shù),直到 FETCH_REQUEST action 被 dispatch儡循。一旦我們獲得了匹配的 action舶吗,中間件就會恢復(fù)執(zhí)行 generator 函數(shù)。

下一條指令 fork(fetchUrl, action.url) 告訴中間件去無阻塞調(diào)用一個新的 fetchUrl 任務(wù)择膝,action.url 作為 fetchUrl 函數(shù)的參數(shù)傳遞誓琼。中間件會觸發(fā) fetchUrl generator 并且不會阻塞 watchFetchRequests。當(dāng)fetchUrl 開始執(zhí)行的時候,watchFetchRequests 會繼續(xù)監(jiān)聽其它的 watchFetchRequests actions踊赠。當(dāng)然呵扛,JavaScript 是單線程的,redux-saga 讓事情看起來是同時進行的筐带。

(3)在 worker saga fetchUrl 中,call(fetch,url) 指示中間件去調(diào)用 fetch 函數(shù)缤灵,同時伦籍,會阻塞fetchUrl 的執(zhí)行,中間件會停止 generator 函數(shù)腮出,直到 fetch 返回的 Promise 被 resolved(或 rejected)帖鸦,然后才恢復(fù)執(zhí)行 generator 函數(shù)。

最后胚嘲,總結(jié)一下 redux-saga 的優(yōu)點:

(1)聲明式 Effects:所有的操作以JavaScript對象的方式被 yield作儿,并被 middleware 執(zhí)行。使得在 saga 內(nèi)部測試變得更加容易馋劈,可以通過簡單地遍歷 Generator 并在 yield 后的成功值上面做一個 deepEqual 測試攻锰。

(2)高級的異步控制流以及并發(fā)管理:可以使用簡單的同步方式描述異步流,并通過 fork 實現(xiàn)并發(fā)任務(wù)妓雾。

(3)架構(gòu)上的優(yōu)勢:將所有的異步流程控制都移入到了 sagas娶吞,UI 組件不用執(zhí)行業(yè)務(wù)邏輯,只需 dispatch action 就行械姻,增強組件復(fù)用性妒蛇。

詳細(xì)代碼可以查看分支:https://github.com/YahuiWong/react-native-typescript/tree/redux-saga?如果覺得有用,請Star?楷拳,謝謝绣夺!

參考:

https://segmentfault.com/a/1190000007248878#articleHeader7

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市欢揖,隨后出現(xiàn)的幾起案子陶耍,更是在濱河造成了極大的恐慌,老刑警劉巖浸颓,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件物臂,死亡現(xiàn)場離奇詭異,居然都是意外死亡产上,警方通過查閱死者的電腦和手機棵磷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晋涣,“玉大人仪媒,你說我怎么就攤上這事。” “怎么了算吩?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵留凭,是天一觀的道長。 經(jīng)常有香客問我偎巢,道長蔼夜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任压昼,我火速辦了婚禮求冷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘窍霞。我一直安慰自己匠题,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布但金。 她就那樣靜靜地躺著韭山,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冷溃。 梳的紋絲不亂的頭發(fā)上钱磅,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音秃诵,去河邊找鬼续搀。 笑死,一個胖子當(dāng)著我的面吹牛菠净,可吹牛的內(nèi)容都是我干的禁舷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼毅往,長吁一口氣:“原來是場噩夢啊……” “哼牵咙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起攀唯,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤洁桌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后侯嘀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體另凌,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年戒幔,在試婚紗的時候發(fā)現(xiàn)自己被綠了吠谢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡诗茎,死狀恐怖工坊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤王污,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布罢吃,位于F島的核電站,受9級特大地震影響昭齐,放射性物質(zhì)發(fā)生泄漏尿招。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一阱驾、第九天 我趴在偏房一處隱蔽的房頂上張望泊业。 院中可真熱鬧,春花似錦啊易、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捆愁,卻和暖如春割去,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昼丑。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工呻逆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菩帝。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓咖城,卻偏偏與公主長得像,于是被迫代替她去往敵國和親呼奢。 傳聞我的和親對象是個殘疾皇子宜雀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容