reduxreact-reduxredux-saga

Redux Saga async/await pattern


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?


Solution

  • 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.