On the first question
It may be just a matter of readability.
Watchers aren't a real "pattern", they just make your code more explicit about its intentions:
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)
}
Second question
Probably you're talking about this kind of flow:
function* watchLoginRequest() {
while (true) {
const action = yield take(getType(employeeActions.login.request))
yield call(handleLoginRequest, action)
}
}
The difference:
The while(true)-take-call flow does not allow executing two instances of a single handler concurrently. It takes one action, then blocks on the call, until the handleLoginRequest()
has finished. If the user clicks the login button before the handler has completed, the correnponding actions are missed.
The takeEvery() flow does allow concurrent handler execution. This might not be what you want.
Redux-saga docs tell how takeEvery()
is implemented under the hood:
const takeEvery = (patternOrChannel, saga, ...args) => fork(function*() {
while (true) {
const action = yield take(patternOrChannel)
yield fork(saga, ...args.concat(action))
}
})
You see, takeEvery()
is non-blocking itself (a fork), and it executes the handler in a non-blocking way (a fork).
A third option
There is also takeLatest()
, which does allow concurrent handler execution, but if there is a previous instance of a handler executing, it cancels it. Redux-saga docs provide its internal implementation, too.
The while(true)-take-call is the best as a login flow, I think. You probably do not want concurrent logins. If you block concurrent logins on UI level, though, these flows are equivalent, but while(true)-take-call is the most explicit and readable.