Redux Saga -等待另一个动作完成,该动作可能已经运行,也可能从未运行过

mrzz3bfm  于 2023-01-05  发布在  其他
关注(0)|答案(1)|浏览(132)

有很多关于同步/等待任务的文章,但是我找不到一个与我的用例匹配的。
我有3个动作-保存、提交和删除实体。当表单的值发生变化时,我调用save,这会触发一个API调用。所以在日常使用中,这只是每隔几秒钟触发一个事件。为了防止不同步,我使用了一个动作通道和缓冲区来确保它按照我想要的方式运行,有点像同步takeLatest。

const saveBuffer = buffers.sliding(1);
function* saveWatcher() {
  const saveChannel = yield actionChannel('SAVE', saveBuffer);

  while (true) {
    const payload = yield take(saveChannel);
    yield call(save, payload);
  }
}

例如,假设save为:

save() {
  try {
    yield delay(5000);

    yield put(actions.saveSuccess());
  } catch (e) {
    yield put(actions.saveError());
  }
}

现在,当我启动删除/提交时,我想确保我们没有处于保存过程中。我以为我可以通过检查缓冲区是否为空来使其工作,但这不起作用,因为空缓冲区仍然可能意味着我们处于保存过程中。
也有可能save从来没有被调用过。例如,我们发布时不做任何更改。
我试过这样的方法:

function* waitForPendingSaves() {
  const hasPendingSaves = !saveBuffer.isEmpty();

  if (hasPendingSaves) {
    yield race([
      take(constants.SAVE_SUCCESS),
      take(constants.SAVE_ERROR),
    ]);
  }
}

但如前所述,这会删除中间保存,因为缓冲项正在出队和处理。我在想,也许是某种切换,当'SAVE'事件处理时继续,然后在'SAVE_SUCCESS/ERROR'完成时再次关闭,但不知道如何做得很好。
当我触发另一个操作时,如何确保save当前没有运行?
我确实希望任务完成,但它可能毫无价值,所以取消它是不可能的。

kqqjbcuj

kqqjbcuj1#

如果你已经在效果级别上去抖了,为什么不在效果级别上添加API呢?这就是去抖的全部意义所在。
是的,这是一个权衡,松散一致性的更好的UX与强一致性的稍微令人讨厌的UX。
另一个解决方案是你不必真的禁用提交按钮。
用户单击“提交”按钮后,您可以在“提交”按钮上添加加载。一旦保存API数组中的所有承诺都被解析/拒绝,您就可以调用“提交API”。在“提交API”被解析后,您可以禁用“提交”按钮的加载。您必须确保在禁用“提交”按钮时也禁用用户输入。否则,如果用户在单击“提交”按钮后继续写入,保存API状态和提交按钮状态将具有不同的最新数据。

相关问题