今日、localStorage を使用して、この同時実行の問題に遭遇しました (2 年後に..)
シナリオ: ブラウザー (Chrome など) の複数のタブには、基本的に同時に実行される同一のスクリプト コードがあります (SignalR などによって呼び出されます)。このコードは、localStorage の読み取りと書き込みを行います。タブは異なるプロセスで実行されますが、共有ローカル ストレージにまとめてアクセスするため、ここにはロック メカニズムがないため、読み取りと書き込みは未定義の結果につながります。私の場合、すべてのタブではなく、1 つのタブのみが実際にローカル ストレージで動作することを確認したかったのです。
上記の質問で述べた Benjamin Dumke-von der Ehe のロック機構を試しましたが、望ましくない結果が得られました。だから私は自分の実験的なコードをロールバックすることにしました:
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);
};
利用方法:
localStorage.lock(ロック名, maxHold ,コールバック);
- lockName - ロックのグローバル スコープの一意の名前 - 文字列
- maxHold - スクリプトを保護する最大時間 (ミリ秒) - 整数
- callback - 保護されるスクリプトを含む関数
例:「1 つのタブでのみサウンドを再生する」
//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 <tm-3000)) {
localStorage.lastMsgBeep = tm;
//msgSound.play();
console.log('beep');
}
});