在 model 中請求服務端數據

******若是說 model,namespace,connect,dispatch,action,reducer 這些是 dva 的基石,那 dva 的精髓就體如今於 effect。*******javascript

關於EffectGenerator function

那麼 effect 究竟是什麼呢 ?effect 是一個 dva 語境中的名詞。和 reducers 相似,咱們也能夠在 dva model 中定義一個 effects 成員。html

export default { namespace: 'some_namespace', state: {}, effects: { // 定義 effects 成員 'someEffect': function*() {}, 'someOtherEffect': function*() {}, // ... }, reducers: { // ... }, }

局部上看 effect 就是一個一個
生成器函數generator function。宏觀上看,effect 是一層中間件。

在上一章中 action 被 dispatch 以後就可以 直接 到達 reducer。爲了保證 reducer 的純粹性,但同時又可以處理反作用,就須要打破「直接」這個特性。effect 充當了這麼一箇中間層,當 action 被 dispatch 以後,會先到達 effect 處理反作用,而後該 effect 最終會促使新的 action 發送出去,這個新的 action 可能被其餘的 effect 再捕獲繼續處理,也可能被 reducer 捕獲並結束,不管怎樣,最終處理邏輯的終點都將是 reducer。java

在上一章節中,咱們知道 action.type 的構造是 namespace 名稱 + / + reducer 名稱,事實上 action.type 也能夠是 namespace 名稱 + / + effect 名稱。對於視圖層來說,其實並不會感知 effect 和 reducer 的區別。視圖層只是經過 action 描述想作什麼,至於這個 action 以後是直接被 reducer 處理仍是經過 effect 再到 reducer,視圖層並不感知,也不該該關心。這樣咱們就作到了數據邏輯和視圖邏輯的分離處理。express

Generator function

咱們再解釋爲何 generator function 能夠用來處理異步邏輯。其實 generator function 處理異步邏輯並非 dva 的專利,在許多 js 框架中都用到了,最著名的就是 co。使用 generator function 處理異步也不是對語言特性的亂用,而是說 generator function 自然地就具有處理異步的特質。dva 中一個典型的 effect 的寫法是:redux

getData: function* ({ payload }, { call, put }) { const data = yield call(SomeService.getEndpointData, payload, 'maybeSomeOtherParams'); yield put({ type: 'getData_success', payload: data }); }

先說結論:當這個 generator function 被執行時,執行的流程 看上去 會是同步的!入參有兩個對象,第一個對象就是匹配這個 effect 的 action 對象,所以能夠取到約定的 payload 這個字段,第二個對象是 effect 原語集,
其中 , 最爲經常使用。generator function 入參中的兩個對象都是在運行時由 dva 注入到 generator function 中的。 實際上是一個函數,和 關鍵字配合使用處理異步邏輯call 第一個參數是一個函數,要求函數返回 Promise,
以後的參數是該函數調用時的入參。yield call 調用後就阻塞了,Promise 被解析後,獲得異步調用的結果,存儲到 data 中,而後程序才能繼續進行。看到下面一行又執行了 put。
也是一個函數,put 和 配合使用,用來派發一個 action,和 dispatch 的功能 如出一轍
只不過是在 effect 函數中使用而已。callputcallyieldputyield

注意: 派發的 action 若是是爲了觸發 同 model 中的其餘 effect/reducer 執行,不須要指定 namespace 名稱。
yield put

 異步的實質是事件發生促使程序的執行點來回跳轉。咱們使用 callback 本質上是描述跳轉的一種手段。generator function 並無改變異步的本質,只是改變了描述的方式,使得程序看起來像是同步同樣。框架

一個 generator function 在執行時有 兩方。一方是 generator function 自己,另外一方是 generator function 的句柄持有者,而這通常都是框架所持有。咱們姑且稱這個句柄爲 genStub。當框架調用 genStub.next() 時,generator function 會執行到下一個 yield 而後暫停,並把 yield 後面表達式的計算值返還給框架,同時把程序執行權交給框架。框架拿到值後作處理,好比就是異步處理,處理結束拿到結果,再次調用 genStub.next(),返還值給 generator function 同時驅動它恢復執行。當恢復執行時,你能夠認爲 返回的處理結果會總體替換 yield <expression>,而後程序繼續執行到下一個 yield。異步

 

yield 這個單詞用在這裏特別形象:yield 自己有「讓步」的意思,也有「產出」的意思。函數

 

「generator function yield 到外部的值」和「外部返還給 generator function 的值」不是一回事!!!spa

 

generator function 定義了流程,並在每次 yield 節點上報想作的事情。而異步的真正執行邏輯由 generator function 句柄的持有者代爲執行。對應到 dva 上也是同樣的。拿 call 作例子,call 實際上是一個特別簡單的函數。call 的返回值只是一個 plain javascript object:3d

 

{
  CALL: { fn: SomeService.getEndpointData, args: [payload, 'maybeSomeOtherParams'] } }

 

咱們經過 call 向 dva 描述了想作的事情:請幫我執行這個函數,Promise 解析後通知我繼續執行,並把 Promise 的解析值返回給我。

相關文章
相關標籤/搜索