Reputation: 12884
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'])
?
Upvotes: 1
Views: 2536
Reputation: 754
NON-BLOCKING
is a Synchronous flow, which means that the Saga disobey the block of codes and simultaneously read the lines within the parent block, the reason why it was called Non-Blocking
BLOCKING
call means that the Saga yielded an Effect and await the previous block before it continuous for the next block execution and basically it was called Blocking
To your case, you just misunderstood the documentation of redux-saga but it was just about like this
import {call, cancel, join, take, put} from "redux-saga/effects"
function* saga() {
yield take(ACTION) // Blocking: will wait for the action
yield call(ApiFn, ...args) // Blocking: will wait for ApiFn (If ApiFn returns a Promise)
yield call(otherSaga, ...args) // Blocking: will wait for otherSaga to terminate
yield put(...) // Non-Blocking: will dispatch within internal scheduler
const task = yield fork(otherSaga, ...args) // Non-blocking: will not wait for otherSaga
yield cancel(task) // Non-blocking: will resume immediately
// or
yield join(task) // Blocking: will wait for the task to terminate
}
For more info just read about the documentation itself of Redux-Saga
Upvotes: 0
Reputation: 53
To simply explain:
yield put({type: 'LOGIN_ERROR',error})
= dispatch action indicating that there is a LOGIN_ERROR.yield take(['LOGOUT', 'LOGIN_ERROR'])
= wait until there is an either LOGOUT or LOGIN_ERROR action to be dispatched and only continue executing the next line which is yield call(Api.clearItem, 'token')
if there is a LOGOUT or LOGIN_ERRORUpvotes: 1
Reputation: 37986
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.
Upvotes: 2