Не удается понять неблокирующие вызовы в Redux-Saga

#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