Redux Saga async/await pattern

跟風遠走 提交于 2019-12-20 09:28:24

问题


I'm using async/await throughout my codebase. Because of this my api calls are defined by async functions

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

I would like to call this function from my saga code. It seems like I can not do this:

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

However, this does work, and matches the redux saga documentation:

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

Is this the correct way to use Redux Saga alongside async/await? It is standard to use this generator syntax inside of the saga code, and the async/await pattern elsewhere?


回答1:


Yes, that's the standard way to use Redux-Saga.

You should never be calling the await function directly inside the saga-generator, because redux-saga is for orchestrating the side-effects. Therefore, any time that you want to run a side-effect you should do it by yielding the side-effect through a redux-saga effect (usually: call or fork). If you do it directly without yielding it through a redux-saga effect, then redux-saga won't be able to orchestrate the side-effect.

If you think about it, the redux-saga generator is completely testable without the need of mocking anything. Also, it helps to keep things decoupled: if your apiFetchFoo returned a promise, the saga would still work the same.




回答2:


As pointed out by Josep, await cannot be used inside a generator. Instead you need to use an async function. Also, note this is a limitation of async function itself. It is not imposed by redux-saga.

Beyond this, I also wanted to mention that it is a conscious choice by the redux-saga authors to not allow devs to express sagas as async/await functions.

Generators are more powerful than async/await and they allow advanced features of redux-saga like co-ordinating parallel tasks.

Moreover, expressing sagas as generators help us define Effects which are plain objects defining the side effect. Effects makes it very easy to test our sagas.

So, although your working code is fine, maybe not mixing up sagas and async function is a good idea.

Just define your apiFetchFoo to return a promise which resolves with the response to the request. And when this happens your saga will resume with the results.

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



回答3:


await always work within a function that's declared as async. #thumbRule

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


来源:https://stackoverflow.com/questions/43443620/redux-saga-async-await-pattern

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!