I've been using the chrome-promise library to wrap the Chrome extension API with a facade that returns promises instead of using callbacks. This has generally worked quite well, but I seem to be running into an issue with chrome.storage.local
APIs.
My extension's event page listens for the chrome.tabs.onActivated
and chrome.tabs.onRemoved
events. When it gets the onActivated
event, it adds the tab info to an array and calls chrome.storage.local.set(data)
to store the updated array in local storage.
When it gets the onRemoved
event, it calls chromepromise.storage.local.get(null).then(...)
to get the list of tabs via a promise, removes the tab info from the array, and then calls chrome.storage.local.set()
again to save the updated array.
The issue is that the onActivated
event seems to trigger before the promise flow from the onRemoved
event resolves. So the onActivated
handler retrieves the old stored array, with the closed tab still in it, and then pushes the newly activated tab. So the stored tab data now includes a tab that's already been closed.
I'm assuming this is an issue with using promises instead of callbacks, but I'm wondering if anyone else has run into this problem with this library and worked around it.
Update
As wOxxOm points out, this is a generic problem with "arbitrating unpredictable asynchronous access to a single resource such as chrome.storage
" and not unique to the chrome-promise
library.
After researching a bit, I came up with a couple solutions, added as answers below. One uses a mutex to ensure (I think) that one promise chain's getting and setting data in chrome.storage
completes before the next one starts. The other queues the whole promise chain that's created from an event and doesn't start the next one until the current one has fully completed. I'm not sure which is better, though I suppose locking for a shorter period of time is better.
Any suggestions or better answers are welcome.