I have an action called initialiseApp which, obviously, initialises the application. There are some things I need from the server, such as the user information, the styles and some details about the page that is being displayed (it is a single page application). I am using redux-sagas and I can't figure out a way to chain asynchronous actions so that they occur IN ORDER, not parallel.
I need the user information to be called BEFORE requesting any styling information, because on the server side, the call for the user goes and retrieves the user and sets up some things in the session. Because the styles are being requested in parallel at the moment, it is showing errors because the user has not been set up yet on the server.
So I've tried using put.sync but that doesn't seem to work, but here is my code so far (I'm also using TypeScript by the way):
private *invokeAndWaitOn(action: IAction<any>) {
const putSync = (put as any).sync; // The typings file for redux-sagas does not yet include put.sync
yield putSync(action);
}
private *invokeArrayOfActions(actions: IAction<any>[]) {
for (let action of actions) {
yield* this.invokeAndWaitOn(action);
}
}
but this doesn't seem to work and I can't find any examples of how to properly use redux-saga's put.sync effect.
Can anyone see what I am doing wrong or is there a better/correct way to do this please?
Thanks in advance.
As a userland library, redux-saga can handle asynchronous behavior in ways that async/await doesn't. The takeLatest() behavior is an example of something that you can't do with async/await: you can't abort an async function once it has started unless the async function errors or returns.
Such a powerful & elegant tool as Redux-Saga, a Redux side effect manager, is said to be deprecated, and no longer being maintained, starting from Jan 27, 2021.
Using Redux Saga to handle multiple async requests Redux Saga then takes care of the invocation and return the result to the generator. The same thing happens with the put method. Instead of dispatching an action inside the generator, put returns an object with instructions for the middleware to dispatch the action.
Redux Saga is a middleware library used to capture the action from the Redux and interact with external services (API) outside asynchronously and communicate with the Redux store. This includes making HTTP requests to external services, accessing browser storage, and executing I/O operations.
Let's assume, for sake of this use-case, you have two actions fetchUser
and fetchStyle
. You want to fire the second action right after the first action succeeded.
In this case you need to have two other actions for each to handle Success and Error so that your actions be as follow:
For user fetching: fetchUser
, fetchUserSuccess
, and fetchUserError
For style fetching: fetchStyle
, fetchStyleSuccess
, and fetchStyleError
then wrap your the whole fetching process in, let's say sagaFunction
as follow:
private* fetchUserSaga() {
try {
yield put(fetchUser());
let response = yield call(/* fetchUser API function */])
yield put(fetchUserSuccess(response));
} catch (err) {
yield put(fetchUserFailure(err));
}
}
Hint: You gotta use call
effect from redux-saga
.
private* fetchStyleSaga() {
try {
yield put(fetchStyle());
let response = yield call(/* fetchStyle API function */])
yield put(fetchStyleSuccess(response));
} catch (err) {
yield put(fetchStyleFailure(err));
}
}
Then pass those sagas functions to your invoker generator function, as follow:
/*
const sagas = [
fetchUserSaga,
fetchStyleSaga,
]; */
private* invokeArrayOfSagas(sagas: ISaga<any>[]) {
for (let saga of sagas) {
yield call(saga()); /* saga: fetchUserSaga || fetchStyleSaga */
}
}
This will wait until the fetchUserSaga is completed then start fetchStyleSaga.
More info: If you want to group some actions and call them in parallel the another bunch of actions depends on them, you can yield them in an array with one yield
keyword, see more here.
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