我见过 sagas 以 3 种方式监听 Action :
<强>1。 while(true) take()
function* onUserDetailsRequest() {
while(true) {
const { userId } = yield take(USER_DETAILS_REQUESTED);
const response = yield call(fetchUserDetails, userId);
put(USER_DETAILS_RECEIVED, response);
}
}
<强>2。 while(take())
function* onUserDetailsRequest() {
while(yield take(USER_DETAILS_REQUESTED)) {
const userId = yield select(userSelectorFn);
const response = yield call(fetchUserDetails, userId);
put(USER_DETAILS_RECEIVED, response);
}
}
<强>3。 takeEvery()
function* onUserDetailsRequest() {
yield takeEvery(USER_DETAILS_REQUESTED, function* (action) {
const { userId } = action;
const response = yield call(fetchUserDetails, userId);
put(USER_DETAILS_RECEIVED, response);
}
}
各自的优缺点是什么?在哪些情况下我们应该使用一个而不是另一个?
最佳答案
用代码澄清@AlexM的答案。
猫测试.js
const { createStore, applyMiddleware } =require('redux')
const createSagaMiddleware =require('redux-saga').default
const { takeEvery ,take,fork}=require('redux-saga/effects')
const {delay} =require('redux-saga')
const sagaMiddleware = createSagaMiddleware()
const reducer=(state=[],action)=>{return [...state,action.type];}
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
function* takeSaga() {
while(true){
const action=yield take('testTake')
console.log(action)
yield delay(1000)
}
}
function* takeEverySaga() {
yield takeEvery('testTakeEvery',function* (action){
console.log(action)
yield delay(1000)
})
}
function* takeSagaWithFork() {
while(true){
const action=yield take('testTakeWithFork')
yield fork(function*(){
console.log(action)
yield delay(1000)
})
}
}
sagaMiddleware.run(takeSaga)
sagaMiddleware.run(takeEverySaga)
sagaMiddleware.run(takeSagaWithFork)
const main=async ()=>{
store.dispatch({type: 'testTake'})
store.dispatch({type: 'testTake'})
store.dispatch({type: 'testTakeEvery'})
store.dispatch({type: 'testTakeEvery'})
store.dispatch({type: 'testTakeWithFork'})
store.dispatch({type: 'testTakeWithFork'})
}
main();
用node test.js
运行上面的代码会输出
{ type: 'testTake' }
{ type: 'testTakeEvery' }
{ type: 'testTakeEvery' }
{ type: 'testTakeWithFork' }
{ type: 'testTakeWithFork' }
你看出区别了吗? takeSaga
的任务在调度第二个 testTake
操作时处于休眠状态,因此 takeSaga
只是忽略了第二个 testTake
操作。但是,对于 takeEverySaga
和 takeSagaWithFork
,每次都会 fork 一个新任务
它接收到一个testTakeEvery
Action ,所以他们在自己的任务“线程”中休眠,因此不会错过新的 Action 。因此,takeEvery
本质上与 while(true)
+take
+fork
相同。
关于javascript - 在 saga : `while(true) take()` vs `while(take())` vs. `takeEvery()` 中监听 Action 的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47909392/