Fetch data in parallel using Redux Saga
Asked Answered
B

1

7

I wish to know what is the proper way in Redux Saga to achieve the following behavior:

  1. An action is dispatched by user interaction.
  2. The appropriate listening saga now tries to fetch data from the API, by calling several async methods in parallel.
  3. Upon every successful response, independently from the rest of the requests, an action is dispatched with the retrieved data (thus updating the UI, etc).
  4. Erroneous responses are gathered and then dispatched with a single action once all requests have finished (in order to later show a single error toast, for instance).

I have successfully implemented it by using the following pattern (sorry I lack full code examples, it isn't available at the moment):

function* fetchData(dataType) {
  const resp = yield call(MyApi.fetchData, dataType);
  if(!resp.err) {
    yield put(fetchDataSuccess, resp.data);
  } else {
    return resp.err;
  }
}

function* mySaga() {
  const errors = yield all([
    call(fetchData, 'typeOne'),
    call(fetchData, 'typeTwo),
    call(fetchData, 'typeThree)
  ]);
  // errors contains the returned errors
}

Is it the best way to achieve the desired effect?

Bioclimatology answered 19/6, 2019 at 15:26 Comment(3)
that looks fine to me - what are your concerns?Intercommunicate
@WillJenkins Feels wrong to have a generator function which sometimes yields action effect and sometimes return an error.Bioclimatology
@Bioclimatology - Nice recipe, Usually I use a separate holder for each API result const [one, two, three] so each holder has its value either result or error. Like in redux-saga APISnatch
M
2

You can use fork effect for sending the requests concurrently https://redux-saga.js.org/docs/advanced/ForkModel.html

So your code will become like

function* fetchData(dataType) {
  const resp = yield call(MyApi.fetchData, dataType);
  if(!resp.err) {
    yield put(fetchDataSuccess, resp.data);
  } else {
    return resp.err;
  }
}

function* mySaga() {
 yield fork(fetchData, 'typeOne');
 yield fork(fetchData, 'typeTwo');
 yield fork(fetchData, 'typeThree');
}

For error handling, you can throw the error from the generator and handle it in the main saga.

Mechanotherapy answered 20/6, 2019 at 12:57 Comment(1)
all effect also fires them concurrently, what's the difference? Can you show a sketch of the main saga? Can't understand how you're planning to record all the errors and handle them together when everything has finished.Bioclimatology

© 2022 - 2024 — McMap. All rights reserved.