Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I always use redux-saga `call` effect for functions that return promise?

Assuming I have a function

function* request(url) {
   return global.fetch(url).then(response =>
     _.result(response, 'json'))
}

Both code examples work fine to me

const {data} = yield call(request, 'http://example.com/api');
yield put(actionSuccess(data));

and

const {data} = yield request('http://example.com/api');
yield put(actionSuccess(data));

Therefore the question. What is an advantage of using the call effect for functions that return promises?

like image 864
Eugene Tiutiunnyk Avatar asked Dec 13 '22 13:12

Eugene Tiutiunnyk


1 Answers

Some benefits of using call():

  1. Testability, the only benefit the docs seem to mention (lower half of the page). I recommend redux-saga-test-plan, it allows to mock call() and other effects by directly supplying the return value.
  2. More fine-grained task cancellation. Sagas are ES6 generators, which only yield control (back to redux-saga middleware) when you use the yield statement. These are the only points where cancellation can happen. A yield call() gives redux-saga an opportunity to cancel the task right before it's about to make that no longer needed call. Task cancellation is performed using gen.return() generator method. [1] [2]
  3. More fine-grained task scheduling in general. Redux-saga's concurrency model is basically cooperative multitasking. And JavaScript is single-threaded. A So when you yield, it's the only opportunity for redux-saga middleware to do any kind of scheduling other tasks. (I'm not sure how good redux-saga is at this, though.)

For more information, I think it's best to open an issue on redux-saga's Github to ask the maintainer directly.

UPD: As this answer is getting attention: think twice before using redux-saga. It provides:

  • A now obsolete generator-based version of async/await available since ES7
  • CSP (channels) Golang users should be familiar with
  • Task cancellation (but you cannot wait for your "cleanup" block to terminate!)

If you want to use Redux, I recommend opting for something simpler, like async thunks. You can have channels with async-csp and proper cancellation with cancellationtoken.

like image 168
Andrey Moiseev Avatar answered May 11 '23 01:05

Andrey Moiseev