Preventing a JavaScript event listener from firing multiple times concurrently (in a Google Chrome extension)
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开发者_如何学JAVA. 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?
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.
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:
- Have a variable called
lastEventTime
- Every time an event happens, update the variable with the current timestamp
- 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.
精彩评论