日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
為什么Redux-Saga不能用AsyncAwait實(shí)現(xiàn)

今天群里有個(gè)小伙伴問了個(gè)問題

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括鯉城網(wǎng)站建設(shè)、鯉城網(wǎng)站制作、鯉城網(wǎng)頁制作以及鯉城網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,鯉城網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到鯉城省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

為什么 saga 不能用 async await 來實(shí)現(xiàn)呢?

想必開始接觸 redux-saga 的同學(xué)都有這個(gè)疑問,為啥為要用 generator 的寫法,用 async await 行不行。

 
 
 
 
  1. import { put, call } from 'redux-saga/effects'
  2. import { loginService } from '../service/request'
  3. function* login(action) {
  4.     try {
  5.         const loginInfo = yield call(loginService, action.account)
  6.         yield put({ type: 'loginSuccess', loginInfo })
  7.     } catch (error) {
  8.         yield put({ type: 'loginFail', error })
  9.     }
  10. }

這個(gè)問題我剛開始用 saga 的時(shí)候也想問,但后來了解了 saga 的原理就想明白了。

下面我們就來探究一下。

saga 原理

我們從組件把 action 發(fā)給 store,這個(gè)過程是同步的。

但是有一些異步的過程加在哪里呢?中間件。

redux saga 會(huì)先把 action 直接透傳給 store,這個(gè)過程是同步的。

然后再傳遞一份給 watcher saga,看一下是否是被監(jiān)聽的 action,如果是交給 worker saga 來處理,worker saga 處理的過程中可以 put 新的 action 到 store,這個(gè)過程是異步的。

這就是 redux-saga 的原理,原理上還是比較簡單的,亮點(diǎn)在于異步過程的組織上,也就是 generator 上。

為什么說用 generator 來組織異步過程是 redux-saga 的亮點(diǎn)呢?

別急,我們先了解下什么是 generator。

generator

生成器(generator)是一個(gè)產(chǎn)生迭代器(iterator)的函數(shù),通過 yield 返回一個(gè)個(gè)值。

而迭代器是一個(gè)有 value 和 done 屬性的對象,用于順序遍歷某個(gè)集合。

我們可以調(diào)用 iterator.next 取到 yield 生成的一個(gè)個(gè)值。

也可以用 Array.from 或者展開運(yùn)算符來取,這是 iterator 的特點(diǎn)。

除了 next 方法,迭代器還有 return 和 throw 方法,就像函數(shù)里的 return 和 throw 語句一樣。

比如用 iterator.return 中止后續(xù)流程

用 iterator.throw 拋出錯(cuò)誤

也就是說 generator 的執(zhí)行是要由一個(gè)執(zhí)行器來控制的,什么時(shí)候取下一個(gè) yield 出的值,什么時(shí)候 next,什么時(shí)候 return 什么時(shí)候 throw 都是由執(zhí)行器控制。

執(zhí)行器可以通過 next、return、throw 的參數(shù)傳遞給 generator 執(zhí)行后的結(jié)果:

上面這段代碼就是一個(gè)小型 saga 了,原理就這么簡單。

那為什么 async await 不行呢?

async await

當(dāng) generator 返回的值都是 Promise,那么執(zhí)行 Promise 以后,只有 resolve 和 reject 兩種結(jié)果,這個(gè)執(zhí)行器就很固定,那自然可以寫一個(gè)通用的執(zhí)行器來自動(dòng)調(diào)用 next、throw 和 return。

這個(gè)就是 async await 的原理,只不過被做成了語法糖。

async await 本質(zhì)上不過是一個(gè) generator 的執(zhí)行器。

如果 redux-saga 用 async await 實(shí)現(xiàn),那么所有的異步邏輯都要命令式的寫在 await 后面,這樣會(huì)導(dǎo)致異步過程很難測試。所以 redux-saga 自己實(shí)現(xiàn)了一個(gè)執(zhí)行器。

再來看這段 saga 的代碼:

 
 
 
 
  1. import { put, call } from 'redux-saga/effects'
  2. import { loginService } from '../service/request'
  3. function* login(action) {
  4.     try {
  5.         const loginInfo = yield call(loginService, action.account)
  6.         yield put({ type: 'loginSuccess', loginInfo })
  7.     } catch (error) {
  8.         yield put({ type: 'loginFail', error })
  9.     }
  10. }

generator 中 yield 出的不是 promise,而是一個(gè)個(gè) effect,這個(gè)其實(shí)就是一個(gè)對象,聲明式的告訴 saga 執(zhí)行器要做什么,而不是命令式的自己實(shí)現(xiàn)。

這樣 generator 的執(zhí)行器就根據(jù)不同的 effect 做不同的實(shí)現(xiàn):

call effect 有對應(yīng)的實(shí)現(xiàn)、put effect 也有對應(yīng)的實(shí)現(xiàn),也就是說 saga 的 generator 執(zhí)行器不像 async await 那樣什么都不做,而是有自己的 runtime 在的。

這樣有什么好處呢?

  • 可以替換 saga effect 具體的執(zhí)行邏輯,易于測試。比如從請求數(shù)據(jù)換成直接返回值,連 mock 都不用了。
  • 可以內(nèi)置一系列的 saga,方便組織異步過程,比如 throttle、debounce、race 等

現(xiàn)在,我們回到最開始那個(gè)問題,redux-saga 能用 async await 實(shí)現(xiàn)么?

能,但是 async await 是一個(gè) generator 的自動(dòng)執(zhí)行器,沒有 runtime 邏輯,要命令式的把異步過程寫在 saga 里。如果自己實(shí)現(xiàn)一個(gè) generator 執(zhí)行器,那么就可以把異步過程抽離出來,方便組織、方便測試。用 async await 實(shí)現(xiàn) saga 的話,那就失去了靈魂。

總結(jié)

redux-saga 的原理是透傳 action 到 store,然后再傳一份 aciton 到 saga 組織的異步過程,saga 分為 watcher saga 和 worker saga。watcher saga 判斷 action 是否要處理,然后交給 wroker saga 處理。

生成器 generator 是返回迭代器 iterator 的函數(shù),iterator 有 next、throw、return 等方法,需要配合一個(gè)執(zhí)行器來執(zhí)行。

async await 本質(zhì)上就是一個(gè) generator 的自動(dòng)執(zhí)行器。

用 async await 實(shí)現(xiàn) redux saga 的話,那就要開發(fā)者命令式的組織異步過程,還難以測試。

所以 redux-saga 自己實(shí)現(xiàn)了一個(gè) generator 執(zhí)行器,自帶 runtime。generator 只要返回 effect 對象來聲明式的說明要執(zhí)行什么邏輯,然后由相應(yīng)的 effect 實(shí)現(xiàn)來執(zhí)行。

這種聲明式的思路除了易于組織異步過程外,還有非常好的可測試性。

generator + saga 執(zhí)行器的設(shè)計(jì)是 redux-saga 的靈魂,所以不能用 async await 來實(shí)現(xiàn)。


分享名稱:為什么Redux-Saga不能用AsyncAwait實(shí)現(xiàn)
網(wǎng)址分享:http://www.dlmjj.cn/article/dpgohgc.html