这个传奇中是否存在并发问题?

时间:2017-11-07 23:51:46

标签: reactjs redux react-redux redux-saga

所以我有一个像这样的传奇

function* watchSelectThing() {
  let currentThing = yield select(getSelectedThing);
  while (true) {
    yield take(types.SELECT_THING);
    const nextSelectedThing = yield select(getSelectedThing);
    if (currentThing !== nextSelectedThing) {
      currentThing = nextSelectedThing;
      yield put(actions.updateSomeOtherThing({}));
      yield put(actions.fetchOtherStuff());
    }
  }
}

有人告诉我,这个传奇可能会错过SELECT_THING行动,因为选择和看跌会阻止这一行动。比如说,如果在2次投注之间触发SELECT_THING动作。我想这似乎是合理的。

如果是这样,是否有某种方式分叉(或做其他事情),同时仍然能够保持currentThing的必要状态,以便可以与nextSelectedThing进行比较?我的大脑现在没有看到它。

1 个答案:

答案 0 :(得分:1)

take等待下一个操作发生,并且没有过去操作的缓冲区。要解决此问题,您可以使用takeLatest

let currentThing

function* saga() {
  currentThing = yield select(getSelectedThing);
  yield takeLatest(types.SELECT_THING, selectThingFlow)
}

function* selectThingFlow() {
  const nextSelectedThing = yield select(getSelectedThing);

  if (currentThing !== nextSelectedThing) {
    currentThing = nextSelectedThing;
    yield put(actions.updateSomeOtherThing({}));
    yield put(actions.fetchOtherStuff());
  }
}

takeLatesttakeEvery之间的区别在于redux-saga如何继续或取消已执行的流程。触发takeLatest操作后SELECT_THING selectThingFlowupdateSomeOtherThing即被取消。因此,无论流程在哪里(例如fetchOtherStuff),都不会再调用下一个操作getSelectedThing,但流程将以takeEvery重新启动。

selectThingFlow但是也会从getSelectedThing开始另一个#ifndef _DEBUG #undef Q_ASSERT #define Q_ASSERT(x) __noop #undef Q_ASSERT_X #define Q_ASSERT_X(cond, where, what) __noop #endif ,但不会取消上一个流程的执行。