我刚进入redux-saga,我对Watchers和Generator有点困惑
例如下面的代码,这就是我的sagas文件的入口点
function* employeesSaga() {
yield all([
takeEvery(getType(employeeActions.login.request), handleLoginRequest),
takeEvery(getType(employeeActions.verifyLogin.request), handleVerifyLoginRequest),
takeEvery(getType(employeeActions.logout), handleLogout)
]);
}
我直接将每个redux调用连接到相应的处理程序。
但是有些人使用观察者,然后他们在该生成器中调用处理程序。这样做的目的是什么?我应该使用那种模式吗?
我还注意到有些人用while(true)
包裹了整个处理程序,这是必要的吗?因为没有它,我的代码也可以正常工作...
答案 0 :(得分:2)
第一个问题
这可能只是可读性问题。
观察者不是真正的“模式”,它们只是使您的代码更加明确地表明其意图:
function* watchLoginRequest() {
yield takeEvery(getType(employeeActions.login.request), handleLoginRequest)
}
function* watchVerifyLoginRequest() {
yield takeEvery(getType(employeeActions.verifyLogin.request), handleVerifyLoginRequest)
}
function* watchLogout() {
yield takeEvery(getType(employeeActions.logout), handleLogout)
}
function* startWatchers() {
yield call(watchLoginRequest)
yield call(watchVerifyLoginRequest)
yield call(watchLogout)
}
function* employeesSaga() {
yield call(startWatchers)
}
第二个问题
可能您正在谈论这种流程:
function* watchLoginRequest() {
while (true) {
const action = take(getType(employeeActions.login.request))
yield call(handleLoginRequest, action)
}
}
区别:
while(true)-take-call 流不允许同时执行单个处理程序的两个实例。它会执行一个操作,然后阻止该呼叫,直到handleLoginRequest()
完成为止。如果用户在处理程序完成之前单击登录按钮,则会错过相应的操作。
takeEvery()流确实允许并发处理程序执行。这可能不是您想要的。
Redux-saga文档在后台告诉how takeEvery()
is implemented:
const takeEvery = (patternOrChannel, saga, ...args) => fork(function*() {
while (true) {
const action = yield take(patternOrChannel)
yield fork(saga, ...args.concat(action))
}
})
您会看到takeEvery()
本身是非阻塞的(派生的),并且以非阻塞的方式执行处理程序(派生的)。
第三个选项
还有takeLatest()
,它允许并发处理程序执行,但是如果有一个先前执行的处理程序实例,则它cancels。 Redux-saga文档也提供了其内部实现。
同时通话(true)是最好的登录流程。您可能不希望并发登录。但是,如果您在UI级别上阻止并发登录,则这些流程是等效的,但是 while(true)-take-call 是最明确和易读的。