这个传奇中有并发问题吗?

Is there a concurrency issue in this 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 行动,因为 select 和看跌期权正在阻止采取行动。比如说,如果在两次放置之间触发了 SELECT_THING 动作。我想这似乎是合理的。

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

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 动作被触发,selectThingFlow 就会被取消。因此,无论流程在哪里(例如 updateSomeOtherThing),下一个操作 fetchOtherStuff 都不会再被调用,但流程将以 getSelectedThing.

重新启动

takeEvery 然而也会开始另一个 selectThingFlowgetSelectedThing 开始但不会取消前一个流程的执行。