Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel of requests through saga

We provide a drop down option at the top..let's say it has options A B C. Whenever user changes the drop down option, a saga gets triggered which makes around 10 different webapi calls.( A map of calls which get executed in parallel)

We use takeLatest helper in saga watcher. So if user immediately changes the dropdown from A to B., Only calls made via B are consumed at client end as takeLatest aborts saga that got triggered by A.

Now , the problem is though only B's calls are consumed, all the A's promise calls that are in pending, also run to completion. Only saga (because of A) gets aborted but not the api calls. We can see that in network tab. So, if user changes between A B C rather quickly, we would have around 30-40 calls to server. All of those run to completion though we are just interested in completion of last 10 calls. If we see in chrome dev tools, last 10 calls are in queue or stalled until the above ones are done. Isn't there a way to propagate the cancellation from saga(takeLatest level)to axios and there by cancelling promises. Axios docs say about cancellation and tokens but I'm not clear about how to propagate cancel in a redux -Saga and axios environment. How to initiate cancel from saga to axios?

like image 288
Sundeep B Avatar asked Apr 28 '18 16:04

Sundeep B


People also ask

How do I stop the execution in Saga?

Once a task is forked, you can abort its execution using yield cancel(task) .

How do you cancel an action in Redux?

​Redux Resource XHR for Redux Resource uses xhr for requests. The action creator exported by this library returns a native XHR object, so you can use the abort method to cancel those requests.

Is Redux-saga deprecated?

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.


2 Answers

const cancelSource = axios.CancelToken.source()
try {
  yield all([
    call(axios.get, "/api/1", { cancelToken: cancelSource.token }),
    call(axios.get, "/api/2", { cancelToken: cancelSource.token }),
    /// ...
  ])
} finally {
  if (yield cancelled()) {
    yield call(cancelSource.cancel)
  }
}
like image 117
apaatsio Avatar answered Oct 22 '22 09:10

apaatsio


If someone is interested in a working solution to this exact problem, I am creator of redux saga library addon specifically to those kind of problems - https://github.com/klis87/redux-saga-requests

It does those kind of things automatically for you - if a saga in cancelled, request is aborted automatically, so you dont even need to think about it.

like image 21
klis87 Avatar answered Oct 22 '22 09:10

klis87