故障排除
添加 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 将等待下一个与模式匹配的动作,然后才会恢复生成器。
要修复上面的示例,yield
由take()
返回的效果
import { take } from 'redux-saga/effects'
function* logActions() {
while (true) {
const action = yield take() // correct
console.log(action)
}
}
我的 Saga 丢失了分派的 action
确保 Saga 没有被某些 effect 阻塞。当 Saga 正在等待 Effect 解决时,它将无法接收分派的 action,直到 Effect 解决。
例如,考虑以下示例
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
如上所示,当 Saga 被 **阻塞调用** 阻塞时,它将错过其间分派的全部 action。
为了避免阻塞 Saga,可以使用 **非阻塞调用**,使用 fork
而不是 call
function* watchRequestActions() {
while (true) {
const { url, params } = yield take('REQUEST')
yield fork(handleRequestAction, url, params) // The Saga will resume immediately
}
}
错误堆栈对于冒泡到根 Saga 的错误不可读
Saga 中的任务本质上是异步的,因此我们必须做一些额外的工作来显示“Saga 堆栈”,就好像它是一系列同步调用一样。因此,从 redux-saga@v1
开始,当错误冒泡到根 Saga 时,库会构建该“Saga 堆栈”并将其作为 onError
回调的第二个参数的 sagaStack: string
属性传递(另请参见 中间件选项),因此您可以将其发送到您的错误跟踪系统或进行其他额外工作。
因此,您可以在控制台中看到类似以下内容。
如果您想为 **开发目的** 获取带有文件名和行号的“Saga 堆栈”,您可以添加 babel-plugin,它允许您获得增强的信息。文档可在 此处 获取。有关 babel-plugin 用法示例,请查看 此示例。
添加 babel-plugin-redux-saga
后,相同的输出看起来像
注意:它也适用于测试,只需确保您(或您的运行器)通过 sagaMiddleware
运行 Saga。