Waiting in a redux-saga
Asked Answered
J

4

16

I want to introduce a delay in a saga (using redux-saga).

How can I do this?

If redux-saga provides an API, I would also be interested in how to achieve it manually.

function* save({ payload }) {
    yield put(pending());
    // I want to simply wait (non-blocking) here for say 2 seconds
    yield put(complete());
}
Jest answered 4/12, 2017 at 13:45 Comment(1)
See the delay function mentioned in the tutorial.Volvox
O
41

Redux-sagas has a special effect for this:

delay(ms, [val])

Returns a Promise that will resolve after ms milliseconds with val.

Example:

import { delay, call } from 'redux-saga/effects'

function* someSaga(input) {
  yield put(someAction())
  yield delay(500)
  yield put(anotherAction())
}
Oidium answered 4/12, 2017 at 14:11 Comment(4)
delay is in 'redux-saga/effects' not in redux-sagaSudanic
@Sudanic that happened after version v1. Thank you to pointed out. I will update my answer.Oidium
instead of writing yield call(delay, 5000) where delay is an effect from redux-saga/effects you should write yield delay(5000) (quoting my console error :) )Graver
@Graver why we should use yield delay(5000) instead of yield call(delay, 5000)? Can you explain more specifically?Brae
A
3

You could achieve that with a promise and a generator function:

function sleep(sec) { 
    return new Promise(resolve => setTimeout(resolve, sec*1000)); 
}

function* save({ payload }) {
    yield put(pending());
    yield sleep(2); //wait 2 seconds
    yield put(complete());
}
Aloisius answered 4/12, 2017 at 13:50 Comment(2)
Would you need to yield the sleep promise?Jest
You need to do something - as written this will call sleep (returning a promise) and then immediately throw it away! If you yield a call() then redux-saga will wait for the promise to resolve, e.g.: yield call(sleep, 2). The best solution is in the answer above - using the delay utility function.Koonce
J
0

Source.

export function delay(ms, val = true) {
  let timeoutId
  const promise = new Promise(resolve => {
    timeoutId = setTimeout(() => resolve(val), ms)
  })

  promise[CANCEL] = () => clearTimeout(timeoutId)

  return promise
}
Jest answered 4/12, 2017 at 13:45 Comment(0)
M
0

Using delay as imported from redux-saga/effects would solve your issue in one line

Martensite answered 2/6, 2022 at 6:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.