#javascript #reactjs #react-native #redux #redux-saga
#javascript #reactjs #react-native #redux #redux-saga
Вопрос:
Я пытаюсь понять раздел документации о redux-saga
неблокирующих вызовах и застрял на приведенном ниже коде
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')
}
}
В объяснении говорится
Если авторизация завершается с ошибкой до выхода пользователя из системы, она отправит действие LOGIN_ERROR, а затем завершится. Таким образом, loginFlow примет LOGIN_ERROR перед выходом из системы, затем он войдет в другую итерацию while и будет ждать следующего действия LOGIN_REQUEST.
Я действительно не могу понять инструкцию, поэтому loginFlow примет LOGIN_ERROR перед выходом из системы, затем он войдет в другую итерацию while и будет ждать следующего действия LOGIN_REQUEST.
Кто-нибудь может объяснить связь между yield put({type: 'LOGIN_ERROR', error})
и yield take(['LOGOUT', 'LOGIN_ERROR'])
?
Ответ №1:
yield put({type: 'LOGIN_ERROR', error})
— отправляет действие типа LOGIN_ERROR
.
yield take(['LOGOUT', 'LOGIN_ERROR'])
приостанавливает выполнение функции генератора ( loginFlow
) до тех пор, пока не будет отправлено действие типа LOGOUT
или LOGIN_ERROR
.
Ответ №2:
Чтобы просто объяснить:
yield put({type: 'LOGIN_ERROR',error})
= действие отправки, указывающее, что имеет место LOGIN_ERROR.yield take(['LOGOUT', 'LOGIN_ERROR'])
= дождитесь отправки действия LOGOUT или LOGIN_ERROR и продолжайте выполнять следующую строку толькоyield call(Api.clearItem, 'token')
при наличии LOGOUT или LOGIN_ERROR
Ответ №3:
НЕБЛОКИРУЮЩИЙ — это синхронный поток, что означает, что Saga не подчиняется блоку кодов и одновременно считывает строки внутри родительского блока, причину, по которой он был вызван Non-Blocking
БЛОКИРУЮЩИЙ вызов означает, что Saga дала эффект и ожидает предыдущего блока, прежде чем он продолжится для выполнения следующего блока, и в основном он был вызван Blocking
В вашем случае вы просто неправильно поняли документацию redux-saga, но это было примерно так
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
}
Для получения дополнительной информации просто прочитайте о самой документации Redux-Saga