问题描述
我试图理解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,password)
yield take(['LOGOUT','LOGIN_ERROR'])
yield call(Api.clearItem,'token')
}
}
解释说
如果在用户注销之前授权失败,它将分派LOGIN_ERROR操作,然后终止。因此,loginFlow将在LOGOUT之前执行LOGIN_ERROR,然后将在另一个迭代中输入,并等待下一个LOGIN_REQUEST动作。
我不太理解语句,所以loginFlow将在LOGOUT之前接受LOGIN_ERROR,然后它将在另一个迭代中进入,并等待下一个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
)的执行,直到调度了LOGOUT
或LOGIN_ERROR
类型的操作为止。
简单解释一下:
-
yield put({type: 'LOGIN_ERROR',error})
=调度操作,指示存在LOGIN_ERROR。 -
yield take(['LOGOUT','LOGIN_ERROR'])
=等待直到要分派LOGOUT或LOGIN_ERROR动作,并且只有在存在LOGOUT或LOGIN_ERROR的情况下,才继续执行下一个yield call(Api.clearItem,'token')
行。
非阻塞
是一个同步流,这意味着 Saga 不遵守代码块并同时读取父块内的行,所以它被称为 Non-Blocking
阻止
call 意味着 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
的文档本身