Are cookie read/write atomic in browser

前端 未结 3 814
孤独总比滥情好
孤独总比滥情好 2020-12-31 04:30

I am trying to implement a cross tab mutex for my needs. I found a implementation here. which seems quite promising. Basically, it implements Leslie Lamport\'s algorithm

3条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-31 05:19

    I ran into this concurrency issue using localStorage today (two years alter..)

    Scenario: Multiple tabs of a browser (e.g. Chrome) have identical script code that gets executed, basically at the same time (called by e.g. SignalR). The code reads and writes to localStorage. Since the tabs run in different processes but access the shared local storage collectively, reading and writing leads to undefined results since a locking mechanism is missing here. In my case I wanted to make sure that only one of the tabs actually works with the local storage and not all of them..

    I tried the locking mechanism of Benjamin Dumke-von der Ehe metioned in the question above but got undesired results. So I decided to roll my own experimental code:

    localStorage 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);        
    };
    

    usage:

    localStorage.lock(lockName, maxHold, callback);

    • lockName - a global scope unique name for the lock - string
    • maxHold - the maximum time to protect the script in milliseconds - integer
    • callback - the function containing the script that gets protected

    example: "only play a 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
    
        // e.g. 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 

提交回复
热议问题