redux-saga原理的解讀(程式碼範例)
這篇文章帶給大家的內容是關於redux-saga原理的解讀(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
筆者最近在做一些後台項目,使用的是Ant Design Pro,其使用了redux-saga處理非同步資料流,本文將對redux-saga的原理做一個簡單的解讀,並將實現一個簡易版的redux-saga。
Generator函數的自動流程控制
在redux-saga中,saga是指一些長時操作,用generator函數表示。 generator函數的強大之處在於其可以手動的暫停、恢復執行,並且可以與函數體外進行數據交互,看如下例子:
function *gen() { const a = yield 'hello'; console.log(a); } cont g = gen(); g.next(); // { value: 'hello', done: false } setTimeout(() => g.next('hi'), 1000) // 此时 a => 'hi' 一秒后打印‘hi'
可以看出來genrator函數何時進行下一步操作完全取決於外部的調度時機,且其內部執行狀態也由外部的輸入決定,這使得generator函數可以很方便的做非同步流程控制。舉個例子,我們先讀取一個檔案的內容作為查詢參數,然後請求一個查詢介面並把傳回的內容印出來:
function getParams(file) { return new Promise(resolve => { fs.readFile(file, (err, data) => { resolve(data) }) }) } function getContent(params) { // request返回promise return request(params) } function *gen() { const params = yield getParams('config.json'); const content = yield getContent(params); console.log(content); }
我們可以手動控制gen函數的執行:
const g = gen(); g.next().value.then(params => { g.next(params).value.then(content => { g.next(content); }) })
以上可以達到我們的目的,但是過於繁瑣,我們想要的是generator函數可以自動的執行,可以寫一個簡易的自動執行函數如下:
function genRun(gen) { const g = gen(); next(); function next(err, pre) { let temp; (err === null) && (temp = g.next(pre)); (err !== null) && (temp = g.throw(pre)); if(!temp.done) { nextWithYieldType(temp.value, next); } } } function nextWithYieldType(value, next) { if(isPromise(value)) { value .then(success => next(null, success)) .catch(error => next(error)) } } genRun(gen);
此時generator函數便可以自動執行,事實上我們可以發現,generator的內部狀態完全是由nextWithYieldType
決定的,我們可以根據yield的類型執行不同的處理邏輯。
Effect
事實上sagaMiddleware.run(saga)可以類似看做genRun(saga),而saga是由一個個的effect組成的,那麼effect是什麼? redux-saga官網的解釋:一個 effect 就是一個 Plain Object JavaScript 對象,包含一些會被 saga middleware 執行的指令。 redux-saga提供了許多Effect創建器,如call、put、take等,已call為例:
function saga*() { const result = yield call(genPromise); console.log(result); }
call(genPromise)
生成的就是一個effect,它可能類似如下:
{ isEffect: true, type: 'CALL', fn: genPromise }
事實上effect只表明了意圖,而實際的行為由類似於上文的nextWithYieldType完成,例如:
function nextWithYieldType(value, next) { ... if(isCallEffect(value)) { value.fn(). then(success => next(null, success)).catch(error => next(error)) } }
當genPromise函數返回的promise被resolve後便會打印出結果。
生產者與消費者
觀察下面的例子
function *saga() { yield take('TEST'); console.log('test...'); } sagaMiddleware.run(test);
saga會在take('TEST')處阻塞,只有執行了dispatch ({type: 'TEST'})後saga才能繼續運作(注意:此時的dispatch方法是經過sagaMiddleware包裝過的)。這給我們的感覺似乎很像是take是一個生產者,在等待disaptch的消費,事實上take只是一個Effect生成器,具體的處理邏輯依然是在nextWithYieldType完成的,類似於:
function nextWithYieldType(value, next) { ... // take('TEST')生成的effect简单的认为是 {isEffect: true, type: 'TAKE', name: 'TEST'} if(isTakeEffect(value)) { channel.take({pattern: value.name, cb: params => next(null, params)}) } }
channel是一個任務產生器,它有兩個方法:take生成任務,put消費任務:
function channel() { /* task = { pattern, cb } */ let _task = null; function take(task) { _task = task; } function put(pattern, args) { if(!_task) return; if(pattern == _task.pattern) _task.cb.call(null, args); } return { take, put } }
#顯然任務是在執行dispatch的時候被消費掉的,這個工作是在sagaMiddleware中做的,類似於如下:
const sagaMiddleware = store => { return next => action => { next(action); const { type, ...payload } = action; channel.put(type, payload); } }
看到這裡我們可以發現,需要我們做的就是不斷的完善nextWithYieldType這個函數,當完成了put、fork、takeEvery對應的邏輯後,一個具備基本功能的redux -saga就誕生啦,就不在贅述這些功能的實現了。
#以上是redux-saga原理的解讀(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
