防止 JavaScript 事件侦听器同时触发多次(在 Google Chrome 扩展中)

发布于 2024-10-15 17:46:50 字数 855 浏览 1 评论 0原文

我已经设置了一个 Google Chrome 扩展程序,可以创建用户书签的上下文菜单。由于 ContextMenus API 必须通过后台页面实现,因此我添加了以下事件侦听器,以便在用户书签发生任何更改时更新上下文菜单:

chrome.bookmarks.onChildrenReordered.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onMoved.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onCreated.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onRemoved.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onImportEnded.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

它在大多数情况下都有效,但我遇到了一个错误我不知道如何杀人。也就是说,如果我同时更改多个书签(例如,通过在书签管理器中选择多个项目并重新排列它们),脚本会同时触发多次,最终会出现上下文菜单的多个实例。

谁能就如何解决这个问题提供任何建议?

I've set up a Google Chrome extension that creates a context-menu of the user's bookmarks. As the ContextMenus API must be implemented through a background page, I added the following event listeners to update the context-menu if there are any changes in the user's bookmarks:

chrome.bookmarks.onChildrenReordered.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onMoved.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onCreated.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onRemoved.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

chrome.bookmarks.onImportEnded.addListener(function () {
    chrome.contextMenus.removeAll();
    contextMenu()
});

It works, for the most part, but I've come across one bug that I cannot work out how to kill. Namely, if I change multiple bookmarks concurrently (for example, by selecting multiple items in the bookmarks manager and re-arranging them), the script fires multiple times concurrently, and I end up with multiple instances of the context-menu.

Can anyone offer any suggestions on how to resolve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北城半夏 2024-10-22 17:46:50

您可以保留一个全局布尔值并用它包装每个事件处理程序:

var lock = false;

chrome.bookmarks.onMoved.addListener(function () {
    if(!lock) {
        lock = true;
        chrome.contextMenus.removeAll();
        contextMenu();
        lock = false;
    }
});

对所有处理程序执行相同的操作。我不知道chrome中如何处理线程,因此在第一次分配完成之前仍然有可能多个线程通过if测试,尤其是对于多核处理器。

You could keep a global boolean and wrap each of your event handlers with it:

var lock = false;

chrome.bookmarks.onMoved.addListener(function () {
    if(!lock) {
        lock = true;
        chrome.contextMenus.removeAll();
        contextMenu();
        lock = false;
    }
});

doing the same for all your handlers. I don't know how threads are handled in chrome, so there is still a possibility of multiple threads getting through the if test before the first assignment is done, especially with multi-core processors.

挖鼻大婶 2024-10-22 17:46:50

我以前从未使用过 chrome 扩展,但如果您想阻止事情同时发生,您通常可以这样做:

  1. 都有一个名为 lastEventTime 的变量
  2. 每次发生事件时 发生时,用当前时间戳更新变量
  3. 每次事件发生时,检查当前时间是否比存储时间晚 2 秒。如果没有,则返回;

这应该确保在第一个事件之后不到两秒发生的任何事件都将被忽略。

我不太确定这是否能解决您的问题,但我希望它能为您指明正确的方向。

I've never worked with chrome extensions before, but if you ever want to prevent things from happening side-by-side, you can usually do something like this:

  1. Have a variable called lastEventTime
  2. Every time an event happens, update the variable with the current timestamp
  3. Every time the event occurs, check to see if the current time is 2 seconds after the stored time. If not, then return;.

This should make sure that any events which happen less than two seconds after the first event will be ignored.

I'm not so sure if that solves your problem, but I hope it points you in the right direction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文