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?
You can transpile async/await into generators, but you can't do the reverse. As a userland library, redux-saga can handle asynchronous behavior in ways that async/await doesn't.
Redux Saga utilizes ES6 generator functions for this. Generators allow for synchronously written asynchronous code. A generator will automatically pause — or yield — at each asynchronous call until it completes before continuing.
An action creator, createPromiseAction() that you can use to define actions which return promises. We call an action that returns a promise a promise action. Saga helpers implementPromiseAction() , resolvePromiseAction() , and rejectPromiseAction() that you use to resolve or reject a promise action's promise.
Sagas are implemented as Generator functions that yield objects to the redux-saga middleware. The yielded objects are a kind of instruction to be interpreted by the middleware. When a Promise is yielded to the middleware, the middleware will suspend the Saga until the Promise completes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With