Redux Saga在循环混乱中

时间:2018-01-30 21:46:12

标签: reactjs redux redux-saga

我有以下(第一次)传奇:

export function* getIdentificators() {
   while (true) {
      yield take(GetIdentificators);
      try {
         const res = yield call(api.getIds);
         const data = // some array of data

         for (const elem of data) {
            yield put(getAnotherStuff(elem));  <--- calling the second saga in a loop
         }
      }
   }
}

如您所见,它会在for of循环中调度某些操作。 它的工作正常,我的意思是 - 这个传奇被称为data长度的多次。

这里有第二个传奇,负责处理getAnotherStuff行动:

export function* anotherStuff() {
   while (true) {
      const action = yield take(someAction);

      const { actionId } = action;
      try {
         const { data } = yield call(apiCall, elem);

         yield put(someSuccessAction(Action, data));
      }
   }
}

所以 - 它不能正常工作。如果我将console.log放入其中,则只会记录一次并且只显示第一个结果。因此它并不像我希望的那样工作(我希望它能像我在第一个传奇中一样多次工作)。

,如果我改为使用takeEvery

export function* anotherStuffWatcher() {
   yield takeEvery(someActionType, anotherStuff);
}

工作正常 - 正在处理所有请求。

我的最后一个问题 - 为什么我使用while(true)它只处理第一个请求而不是每一个请求?为什么我使用takeEvery时它能正常工作?谢谢!

1 个答案:

答案 0 :(得分:1)

  

仅记录一次

这是因为call阻止了效果。假设apiCall需要一些时间。因此,当这个电话正在发生时,你的传奇被封锁,并没有采取新的行动。

export function* anotherStuff() {
   while (true) {
      const action = yield take(someAction);

      const { actionId } = action;
      try {
         const { data } = yield call(apiCall, elem); // this is blocking call

         yield put(someSuccessAction(Action, data));
      }
   }
}

为了避免这种情况,您可以使用takeEvery帮助程序来处理与模式匹配的“采取一切”操作。或者您可以使用actionChannel缓冲未来的行动

export function* anotherStuff() {

   // buffers up to 10 actions
   // or you could provide another buffering strategy via
   // second argument https://redux-saga.js.org/docs/api/#buffers
   const someChannel = yield actionChannel(someAction);

   while (true) {
      const action = yield take(someChannel);

      const { actionId } = action;
      try {
         const { data } = yield call(apiCall, elem); // this is blocking call

         yield put(someSuccessAction(Action, data));
      } catch(blackhole) {}
   }
}