Redux Saga -等待另一个操作完成,这个操作可能运行过,也可能没有运行过



有很多关于同步/等待任务的文章,但是我找不到一篇符合我用例的。

我有3个动作-保存,提交和删除,一个实体。当表单的值发生变化时,我调用save,这会触发API调用。所以在日常使用中,每隔几秒就会触发一个事件。为了避免不同步,我使用了一个动作通道和缓冲区来确保它按照我想要的方式运行,有点像同步的takelest。

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当前未运行?

如果我确实想完成这个任务,那么它可能一文不值,所以取消它是不可能的。

如果你已经在效果级别上发布了,为什么不在效果级别上添加API呢?这就是揭发的全部意义?

是的,这是一个权衡,松散一致性的更好的UX与强一致性的稍微令人讨厌的UX。

另一个解决方案是,你不必真的禁用提交按钮。

在用户点击提交按钮后,你可以在提交按钮上添加一个加载,一旦保存API数组中的所有承诺都被解析/拒绝,你就可以调用提交API,在提交API被解析后,你可以禁用提交按钮的加载。您必须确保在禁用提交按钮时也禁用用户输入。否则,如果用户在点击提交按钮后继续写入,则保存API状态和提交按钮状态将显示不同的最新数据。

最新更新