web-dev-qa-db-ja.com

佐賀でのアクションをリッスンする最良の方法: `while(true)take()` vs `while(take())` vs. `takeEvery()`

私はサガが3つの方法で行動を聞いているのを見てきました:

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);
  }
}    

。takeEvery()

function* onUserDetailsRequest() {
  yield takeEvery(USER_DETAILS_REQUESTED, function* (action) {
    const { userId } = action;
    const response = yield call(fetchUserDetails, userId);
    put(USER_DETAILS_RECEIVED, response);
  }
}

それぞれの長所と短所は何ですか?そして、どのシナリオで次々に使用する必要がありますか?

10
Ali Saeed

@AlexMの答えをコードで明確にするため。

_cat test.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のタスクは、2番目のtestTakeアクションがディスパッチされたときにスリープしているため、takeSagaは2番目のtestTakeアクションを単に無視しました。ただし、takeEverySagatakeSagaWithForkの場合、testTakeEveryアクションを受信するたびに新しいタスクがフォークされたため、彼らは独自のタスク「スレッド」でスリープしていたため、新しいアクションが勝ちました見逃すことはありません。したがって、takeEveryは基本的にwhile(true) + take + forkと同じです。

12
Benjamin