I ran into this concurrency problem using localStorage today (changed two years ..)
Scenario. Several browser tabs (e.g. Chrome) have the same script code that runs, mostly at the same time (called, for example, SignalR). The code reads and writes to localStorage. Since the tabs are executed in different processes, but share a common local drive, reading and writing will lead to undefined results, since there is no locking mechanism here. In my case, I wanted to make sure that only one of the tabs really works with local storage, and not with all.
I tried the locking mechanism of Benjamin Dumke-von der Ehe, which I mentioned in the question above, but got undesirable results. So I decided to overturn my own experimental code:
local storage lock:
Object.getPrototypeOf(localStorage).lockRndId = new Date().getTime() + '.' + Math.random(); Object.getPrototypeOf(localStorage).lock = function (lockName, maxHold, callback) { var that = this; var value = this.getItem(lockName); var start = new Date().getTime(); var wait = setInterval(function() { if ((value == null) || (parseInt(value.split('_')[1]) + maxHold < start)) { that.setItem(lockName, that.lockRndId + '_' + start); setTimeout(function () { if (that.getItem(lockName) == (that.lockRndId + '_' + start)) { clearInterval(wait); try { callback(); } catch (e) { throw 'exeption in user callback'; } finally { localStorage.removeItem(lockName); } } }, 100); } }, 200); };
using:
localStorage.lock (lockName, maxHold, callback);
- lockName - globally unique name for the lock string
- maxHold - maximum time to protect the script in milliseconds - integer
- callback - function containing a protected script
example: "play only sound in one tab
//var msgSound = new Audio('/sounds/message.mp3'); localStorage.lock('lock1', 5000, function(){ // only one of the tabs / browser processes gets here at a time console.log('lock aquired:' + new Date().getTime()); // work here with local storage using getItem, setItem // eg only one of the tabs is supposed to play a sound and only if none played it within 3 seconds var tm = new Date().getTime(); if ((localStorage.lastMsgBeep == null)||(localStorage.lastMsgBeep <tm-3000)) { localStorage.lastMsgBeep = tm; //msgSound.play(); console.log('beep'); } });
AJBauer Jan 22 '16 at 20:22 2016-01-22 20:22
source share