¿Son las cookies de lectura / escritura atómicas en el browser?

Estoy tratando de implementar un mutex de tabulación cruzada para mis necesidades. Encontré una implementación aquí . lo cual parece bastante prometedor Básicamente, implementa el algorithm de Leslie Lamport con necesidades de lectura / escritura atómica para crear un mutex.

Sin embargo, depende de localStorage que proporciona lecturas / escrituras atómicas. Esto funciona bien en la mayoría de los browseres, excepto en Chrome.

Entonces mi pregunta es, ¿puedo usar cookies de lectura / escritura? ¿Las cookies son de lectura / escritura atómica en todos los browseres mainstream (IE, Chrome, Safari, Firefox)?

Ni las cookies ni localStorage proporcionan transactions atómicas.

Creo que es posible que hayas malinterpretado esa publicación de blog, no dice que su implementación no funciona en Chrome, no depende de que localStorage proporcione lecturas / escrituras atómicas . Él dice que el acceso de localStorage normal es más volátil en Chrome. Supongo que esto está relacionado con el hecho de que Chrome usa un process separado para cada pestaña, mientras que la mayoría de los browseres tienden a usar un solo process para todas las tabs. Su código implementa un sistema de locking en la parte superior de localStorage que debería proteger contra la sobreescritura.

Otra solución sería usar IndexedDB . IndexedDB proporciona transactions atómicas. Al ser un nuevo estándar, no es compatible con tantos browseres como localStorage , pero sí con un buen soporte en las versiones recientes de Firefox, Chrome e IE10.

No. Incluso si los browseres probablemente implementan un locking de lectura y escritura en la cookie, no lo protegerá de los cambios que ocurren entre una lectura y una escritura subsiguiente. Esto es fácil de ver mirando las API de JavaScript para las cookies , no hay ninguna function mutex allí …

Me encontré con este problema de concurrency usando localStorage hoy (dos años después …)

Escenario: varias tabs de un browser (por ejemplo, Chrome) tienen código de script idéntico que se ejecuta, básicamente al mismo time (llamado por ejemplo, SignalR). El código lee y escribe en localStorage. Dado que las tabs se ejecutan en diferentes processs pero acceden al almacenamiento local compartido de forma colectiva, la lectura y la escritura conducen a resultados indefinidos, ya que aquí falta un mecanismo de locking. En mi caso, quería asegurarme de que solo una de las tabs realmente funciona con el almacenamiento local y no todas.

Probé el mecanismo de locking de Benjamin Dumke-von der Ehe mencionado en la pregunta anterior, pero obtuve resultados no deseados. Así que decidí rodar mi propio código experimental:

locking localStorage:

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

uso:

localStorage.lock ( lockName , maxHold , callback );

  • lockName : un nombre exclusivo de scope global para el locking – cadena
  • maxHold : el time máximo para proteger el script en milisegundos – integer
  • callback : la function que contiene el script que se protege

ejemplo: "solo reproduce un sonido en una sola pestaña"

 //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 aquinetworking:' + 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'); } });