Search code examples
javascriptreactjsreact-nativereduxredux-saga

Unable to understand non-blocking calls in Redux-Saga


I'm trying to understand Non-blocking calls section of redux-saga documentation and stuck with the below code

import { fork, call, take, put } from 'redux-saga/effects'
import Api from '...'

function* authorize(user, password) {
  try {
    const token = yield call(Api.authorize, user, password)
    yield put({type: 'LOGIN_SUCCESS', token})
    yield call(Api.storeItem, {token})
  } catch(error) {
    yield put({type: 'LOGIN_ERROR', error})
  }
}

function* loginFlow() {
  while (true) {
    const {user, password} = yield take('LOGIN_REQUEST')
    yield fork(authorize, user, password)
    yield take(['LOGOUT', 'LOGIN_ERROR'])
    yield call(Api.clearItem, 'token')
  }
}

The explanation says

If the authorize fails before the user logs out, it will dispatch a LOGIN_ERROR action, then terminate. So loginFlow will take the LOGIN_ERROR before the LOGOUT then it will enter in a another while iteration and will wait for the next LOGIN_REQUEST action.

I can't really understand the statement So loginFlow will take the LOGIN_ERROR before the LOGOUT then it will enter in a another while iteration and will wait for the next LOGIN_REQUEST action.

Can anyone explain the relation between yield put({type: 'LOGIN_ERROR', error}) and yield take(['LOGOUT', 'LOGIN_ERROR'])?


Solution

  • yield put({type: 'LOGIN_ERROR', error}) - dispatches action of type LOGIN_ERROR.

    yield take(['LOGOUT', 'LOGIN_ERROR']) suspends generator function (loginFlow) execution until action of type LOGOUT or LOGIN_ERROR is dispatched.