有很多关于同步/等待任务的文章,但是我找不到一个与我的用例匹配的。
我有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
当前没有运行?
我确实希望任务完成,但它可能毫无价值,所以取消它是不可能的。
1条答案
按热度按时间kqqjbcuj1#
如果你已经在效果级别上去抖了,为什么不在效果级别上添加API呢?这就是去抖的全部意义所在。
是的,这是一个权衡,松散一致性的更好的UX与强一致性的稍微令人讨厌的UX。
另一个解决方案是你不必真的禁用提交按钮。
用户单击“提交”按钮后,您可以在“提交”按钮上添加加载。一旦保存API数组中的所有承诺都被解析/拒绝,您就可以调用“提交API”。在“提交API”被解析后,您可以禁用“提交”按钮的加载。您必须确保在禁用“提交”按钮时也禁用用户输入。否则,如果用户在单击“提交”按钮后继续写入,保存API状态和提交按钮状态将具有不同的最新数据。