无法理解 Redux-Saga 中的非阻塞调用

Unable to understand non-blocking calls in Redux-Saga

我正在尝试理解 redux-saga 文档的 Non-blocking calls 部分并坚持使用以下代码

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')
  }
}

解释说

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.

我真的无法理解语句 所以 loginFlow 将在 LOGOUT 之前使用 LOGIN_ERROR 然后它将进入另一个 while 迭代并等待下一个 LOGIN_REQUEST行动.

谁能解释一下yield put({type: 'LOGIN_ERROR', error})yield take(['LOGOUT', 'LOGIN_ERROR'])之间的关系?

yield put({type: 'LOGIN_ERROR', error}) - 调度 LOGIN_ERROR.

类型的操作

yield take(['LOGOUT', 'LOGIN_ERROR']) 暂停生成器函数 (loginFlow) 执行,直到调度 LOGOUTLOGIN_ERROR 类型的操作。

简单说明一下:

  • yield put({type: 'LOGIN_ERROR',error}) = dispatch action 表示有一个 LOGIN_ERROR.
  • yield take(['LOGOUT', 'LOGIN_ERROR']) = 等到有一个 LOGOUT 或 LOGIN_ERROR 动作被调度,并且只有在有一个 LOGOUT 或 [= 时才继续执行下一行 yield call(Api.clearItem, 'token') 21=]

非阻塞 是一个Synchronous flow,也就是说Saga违背代码块,同时读取父块内的行,所以叫Non-Blocking

阻塞 调用意味着 Saga 产生了一个 Effect 并等待前一个块,然后它继续执行下一个块,基本上它被称为 Blocking

对于你的情况,你只是误解了 redux-saga 的文档,但它就像 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
}

有关更多信息,请阅读 Redux-Saga

的文档本身