Redux Saga async/await 模式

Redux Saga async/await pattern

我在整个代码库中使用 async/await。因此,我的 api 调用由异步函数定义

async function apiFetchFoo {
  return await apiCall(...);
}

我想从我的 saga 代码中调用这个函数。看来我做不到:

// Doesn't work
function* fetchFoo(action) {
  const results = await apiFetchFoo();
  yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}

然而,这确实有效,并且与 redux saga 文档相匹配:

// Does work
function* fetchFoo(action) {
  const results = yield call(apiFetchFoo);
  yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}

这是与 async/await 一起使用 Redux Saga 的正确方法吗?在 saga 代码中使用此生成器语法是标准的,而在其他地方使用 async/await 模式?

是的,这是使用 Redux-Saga 的标准方式。

你不应该直接在 saga-generator 中调用 await 函数,因为 redux-saga 是为了编排 副作用。因此,任何时候你想要 运行 一个副作用,你应该通过 redux-saga 效果产生副作用(通常:callfork) .如果你直接这样做而不通过 redux-saga 效果产生它,那么 redux-saga 将无法协调副作用。

如果你仔细想想,redux-saga 生成器是完全可测试的,不需要模拟任何东西。此外,它有助于保持事情的解耦:如果你的 apiFetchFoo 返回了一个承诺,那么 saga 仍然可以正常工作。

await 始终在声明为 async 的函数中工作。 #thumbRule

async function fetchList () {
  let resp = await fetchApi([params]);
}

正如 Josep 所指出的,await 不能在生成器内部使用。相反,您需要使用 async function。另外,请注意这是异步函数本身的限制。它不是 redux-saga 强加的。

除此之外,我还想提一下,redux-saga 作者 conscious choice 允许开发人员将传奇表达为 async/await 函数。

生成器比 async/await 更强大,它们允许 redux-saga 的高级功能,如 co-ordinating parallel tasks

此外,将 sagas 表示为生成器有助于我们定义 Effects which are plain objects defining the side effect. Effects makes it very easy to test our sagas

所以,虽然您的工作代码很好,但也许不要混淆 sagas 和异步函数是个好主意。

只需将您的 apiFetchFoo 定义为 return 承诺,该承诺会随着对请求的响应而解决。当这种情况发生时,您的传奇将以 results.

继续
 const apiFetchFoo = () =>
   fetch('foo')
     .then(res => res.json())

正如前面的答案所说,Redux saga 使用副作用来处理其中的异步,所以这样做的方式是使用 yield 和 call if calling an API 等等