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

上一篇博客我們用理論和代碼實踐介紹了 使用redux 發(fā)起action 在reducers里生成state 然后重新渲染組件

Redux 的核心理念是嚴格的單向數(shù)據(jù)流板辽,只能通過 dispatch(action) 的方式修改 store,流程如下:

view ->  action -> reducer -> store

但是在業(yè)務(wù)復雜的以及和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-thunkredux-saga瓶籽。

redux-thunk

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

function add() {
    return {
        type: 'ADD',
    }
}

function addIfOdd() {
    return (dispatch, getState) => {
        const currentValue = getState();
        if (currentValue % 2 == 0) {
            return false;
        }
        //分發(fā)一個任務(wù)
        dispatch(add())
    }
}

詳細代碼可以查看分支: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椅贱,當接收到 action 或者知道其被觸發(fā)時懂算,調(diào)用 worker saga 執(zhí)行任務(wù)
root saga
立即啟動 sagas 的唯一入口

? 如何使用?
首先庇麦,我們得在文件入口中加入 saga 中間件计技,并且啟動它,它會一直運行:

//...
import { createStore, applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';
import appReducer from './reducers';
import rootSaga from './saga';
//...

const sagaMiddleware = createSagaMiddleware()

const store=createStore(rootReducer,applyMiddleware(sagaMiddleware));

sagaMiddleware.run(rootSaga)

render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('app')
);

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

import {delay} from 'redux-saga';
import {put,takeEvery,all} from 'redux-saga/effects';
import {ADD} from './actionsTypes';
function* addSync(){
    yield delay(1000);
    yield put({type:ADD})
}
function* watchaddSync(){
yield takeEvery("addSync",addSync)
}

export default function* rootSaga(){
    yield all([
        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,中間件就會恢復執(zhí)行 generator 函數(shù)祠墅。

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

(3)在 worker saga fetchUrl 中,call(fetch,url) 指示中間件去調(diào)用 fetch 函數(shù)娶耍,同時免姿,會阻塞fetchUrl 的執(zhí)行,中間件會停止 generator 函數(shù)榕酒,直到 fetch 返回的 Promise 被 resolved(或 rejected)胚膊,然后才恢復執(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 就行碌廓,增強組件復用性传轰。

詳細代碼可以查看分支: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閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贾铝,居然都是意外死亡隙轻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門垢揩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玖绿,“玉大人,你說我怎么就攤上這事叁巨“叻耍” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵锋勺,是天一觀的道長蚀瘸。 經(jīng)常有香客問我狡蝶,道長,這世上最難降的妖魔是什么贮勃? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任贪惹,我火速辦了婚禮,結(jié)果婚禮上寂嘉,老公的妹妹穿的比我還像新娘奏瞬。我一直安慰自己,他們只是感情好泉孩,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布硼端。 她就那樣靜靜地躺著,像睡著了一般寓搬。 火紅的嫁衣襯著肌膚如雪珍昨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天订咸,我揣著相機與錄音曼尊,去河邊找鬼。 笑死脏嚷,一個胖子當著我的面吹牛骆撇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播父叙,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼神郊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了趾唱?” 一聲冷哼從身側(cè)響起涌乳,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甜癞,沒想到半個月后夕晓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡悠咱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年蒸辆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片析既。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡躬贡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出眼坏,到底是詐尸還是另有隱情拂玻,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站檐蚜,受9級特大地震影響魄懂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜熬甚,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一逢渔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乡括,春花似錦肃廓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敷扫,卻和暖如春哀蘑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葵第。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工绘迁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卒密。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像哮奇,于是被迫代替她去往敵國和親膛腐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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