Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining asynchronous actions using redux-sagas

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.

like image 345
Anupheaus Avatar asked Dec 22 '16 12:12

Anupheaus


People also ask

Can we use async await in Redux saga?

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.

Is Redux saga still used?

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.

When should I use Redux saga?

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.

How do Redux sagas work?

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.


1 Answers

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.

like image 92
Basim Hennawi Avatar answered Oct 21 '22 15:10

Basim Hennawi