javascript - 在 saga : `while(true) take()` vs `while(take())` vs. `takeEvery()` 中监听 Action 的最佳方式

标签 javascript ecmascript-6 redux-saga

我见过 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 操作。但是,对于 takeEverySagatakeSagaWithFork,每次都会 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/

相关文章:

javascript - react : Search Filter is not working Properly

javascript - 在 Typescript 中向创建的 Redux Store 添加属性

javascript - 我如何使用 Javascript 缩放 div 内容及其大小?

javascript - 一种将自定义 JavaScript 函数添加到方法调用链中的 native 方法

javascript - 在 ES6 中将纯类注入(inject) angular 1.x 应用程序的正确方法

javascript - jQuery $(this) 在 nodejs 模块上是 "undefined"(使用 Browserify)

react-native - 当使用 redux-saga 和 react-native-web 时,我们收到错误 `Cannot read property ' mark' of undefined`

reactjs - Redux saga 未在实时套接字上调度操作

javascript - bootstrap scrollspy 跳过第一个元素

javascript - 多线图 x 轴刻度未与数据点对齐