【发布时间】:2020-07-12 11:32:10
【问题描述】:
每次触发某些浏览器事件时(例如,当浏览器选项卡关闭时),我都需要更新一些数据:
chrome.tabs.onRemoved.addListener(async (tabId) => {
let data = await getData(); // async operation
... // modify data
await setData(data); // async operation
});
问题是,当多个此类事件快速连续触发时,异步 getData() 可能会在 setData() 有机会在较早的事件中完成之前在随后的事件处理程序调用中返回陈旧的结果,从而导致结果不一致。
如果事件处理程序可以同步执行,则不会出现此问题,但getData() 和setData() 都是异步操作。
这是竞争条件吗?处理此类逻辑的推荐模式是什么?
--- 更新---
为了提供更多上下文,getData() 和 setData() 只是一些 Chrome 存储 API 的承诺版本:
async function getData() {
return new Promise(resolve => {
chrome.storage.local.get(key, function(data) => {
// callback
});
});
}
async function setData() {
return new Promise(resolve => {
chrome.storage.local.set({ key: value }, function() => {
// callback
});
});
}
出于可读性目的,我将 API 调用包装在 Promise 中,但我认为无论哪种方式都是异步操作?
【问题讨论】:
-
是的,这是一个经典的比赛条件。使用信号量或队列。
-
请告诉我们
getData和setData究竟做了什么。也许有一个特定于该 API 的解决方案 - 例如数据库中的事务。 -
谢谢@Bergi,我在上面做了更新。
-
@winniethemu 谢谢。那就看看Best way to prevent race condition in multiple chrome.storage API calls?吧(虽然我不确定有没有好的解决方案)
-
将回调放到队列中,这并不复杂,只需观察一个数组然后触发推送函数。在我的测试中,它异步但同步处理.. 见 sn-p:playcode.io/634360 我赞成但不会回答,欢迎您
标签: javascript asynchronous events promise