问题 IE localStorage事件失误了


在Internet Explorer 9和10中,localStorage实现意外触发事件(这里的大线程: Chrome的localStorage实施有什么问题?

有没有人知道如何阻止 storage 在Internet Explorer中启动更改的选项卡上触发事件?

例如,单击添加按钮时,以下内容不应显示警告,但在IE中则显示:

小提琴: http://jsfiddle.net/MKFLs/

<!DOCTYPE html>
<html>
  <head>
    <title>Chrome localStorage Test</title>
    <script type="text/javascript" >

      var handle_storage = function () {
        alert('storage event');
      };

      window.addEventListener("storage", handle_storage, false);

    </script>
  </head>
  <body>
    <button id="add" onclick="localStorage.setItem('a','test')">Add</button>
    <button id="clear" onclick="localStorage.clear()">Clear</button>
  </body>
</html>

编辑: 另外,我在这里打开了一个MS的错误。 https://connect.microsoft.com/IE/feedback/details/798684/ie-localstorage-event-misfired

也许它不会被关闭.....


2823
2017-08-27 22:32


起源

@EricLaw感谢编辑:) - Jesse


答案:


将脚本更改为以下内容可防止在焦点窗口中处理任何存储事件。

这并不是你所要求的,因为我认为这需要修补程序,但它会使IE 9/10符合规范,同时对其他浏览器(全局和监听器除外)没有任何负面影响。

<script type="text/javascript" >
      var focused;

      window.addEventListener('focus', function(){focused=1;}, false);
      window.addEventListener('blur', function(){focused=0;}, false);

      var handle_storage = function (e) {
        if(!focused)
          alert("Storage",focused);
      };

      window.addEventListener("storage", handle_storage, false);

</script>

看到 这个小提琴 对于更新的,符合规范的行为。

编辑:以下也可以工作,并以窗口焦点的运行时检查为代价避免侦听器:

<script type="text/javascript" >

      var handle_storage = function (e) {
        if(!document.hasFocus())
          alert("Storage");
      };

      window.addEventListener("storage", handle_storage, false);

</script>

13
2017-09-04 23:14



一个不需要额外的变量: stackoverflow.com/a/8235434/255363 (我测试过 - 它适用于IE9 +,其中出现了存储事件) - kirilloid


如果您正在寻找解决方法,可以使用信号量为localStorage编写包装器。

试试这个(未经测试):

var BetterStorage = {
    _semaphore: false,
    setItem: function(key, item) {
        var that = this;
        this._semaphore = 1; // only this tab
        localStorage.setItem(key, item);
        this._semaphore = 0;
        // or setTimeout(function(){that._semaphore = 0}, 10)
        // based on event-fire time (immedietaly or after short delay?)
        // not tested
    },
    getItem: function() {/*code*/},
    createHandler: function(f) {
        var that = this;
        return function(e){
            if (that._semaphore) { // execution of event is blocked
                return false;
            }
            else {
                return f(e);
            }
        }
    }
}


var handle_storage = BetterStorage.createHandler(function () {
        alert('storage event');
});
window.addEventListener("storage", handle_storage, false);

0
2017-09-07 00:36



此解决方案不起作用 - setItem完成并在触发事件之前返回,因此信号量已经被清除。 - Theo Spears