跳至主要內容

疑難排解

加入 saga 後,應用程式凍結

請確定你從產生器函數中yield效果。

考慮以下範例

import { take } from 'redux-saga/effects'

function* logActions() {
while (true) {
const action = take() // wrong
console.log(action)
}
}

這會讓應用程式進入無限迴圈,因為take()只會建立效果的描述。除非你讓中介軟體對其yield以執行,否則while迴圈會像一般的while迴圈般執行,並讓你的應用程式凍結。

加入yield會暫停產生器,並將控制權交還給 Redux Saga 中介軟體,由其執行效果。對於take(),Redux Saga 將會等待符合模式的下一個動作,並在等到後才會恢復執行產生器。

若要修正上面的範例,請對由take()傳回的效果yield

import { take } from 'redux-saga/effects'

function* logActions() {
while (true) {
const action = yield take() // correct
console.log(action)
}
}

我的 Saga 漏了某些已發送的動作

請確認該傳奇人物不受某些效應阻擋。傳奇人物在等待效應解決時,將無法採取分派動作,直到該效應得到解決。

例如,考慮這個範例

function* watchRequestActions() {
while (true) {
const { url, params } = yield take('REQUEST')
yield call(handleRequestAction, url, params) // The Saga will block here
}
}

function* handleRequestAction(url, params) {
const response = yield call(someRemoteApi, url, params)
yield put(someAction(response))
}

watchRequestActions 執行 yield call(handleRequestAction, url, params),它將等待 handleRequestAction,直到它終止並返回,然後繼續進行下一個 yield take。例如,假設我們有這個事件順序

UI                     watchRequestActions             handleRequestAction
-----------------------------------------------------------------------------
.......................take('REQUEST').......................................
dispatch(REQUEST)......call(handleRequestAction).......call(someRemoteApi)... Wait server resp.
.............................................................................
.............................................................................
dispatch(REQUEST)............................................................ Action missed!!
.............................................................................
.............................................................................
.......................................................put(someAction).......
.......................take('REQUEST')....................................... saga is resumed

如上圖所示,當傳奇人物被 封鎖呼叫 阻擋時,它將遺漏其間分派的所有動作。

若要避免封鎖傳奇人物,你可以使用 fork 代替 call 使用 非封鎖呼叫

function* watchRequestActions() {
while (true) {
const { url, params } = yield take('REQUEST')
yield fork(handleRequestAction, url, params) // The Saga will resume immediately
}
}

傳遞到根傳奇人物的錯誤的錯誤堆疊無法讀取

根據其性質,傳奇人物中的任務是異步的,因此我們必須做一些額外的作業才能顯示「傳奇人物堆疊」,因為它是同步呼叫鏈。因此,從 redux-saga@v1 開始,當錯誤傳遞到根傳奇人物時,函式庫會建置該「傳奇人物堆疊」,並將其傳遞為 onError 呼叫的第二個引數的 sagaStack: string 屬性(另請參閱中介軟體選項),因此你可以將其傳送至你的錯誤追蹤系統或進行其他額外的作業。

因此,你可以在主控台中看到類似這樣的內容。

saga-error-stack.png

如果你想在開發目的中使用具有檔案名稱和行號的「傳奇人物堆疊」,你可以新增babel-plugin,它允許你獲得增強的資訊。文件 在此。有關 babel-plugin 使用範例,請查看此範例

新增 babel-plugin-redux-saga 之後,相同的輸出如下所示

saga-error-stack-with-babel-plugin.png

註:它也適用於測試,只要確保你(或你的執行者)透過 sagaMiddleware 執行傳奇人物即可。

saga-error-stack-node.png