Redux Saga async/await pattern

mattnedrich picture mattnedrich · Apr 17, 2017 · Viewed 22.2k times · Source

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?

Answer

Josep picture Josep · Apr 17, 2017

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.