通过localStorage实现StorageEvent

时间:2017-06-22 22:46:52

标签: javascript asynchronous event-handling local-storage setinterval

因为StorageEvent does not work here,我想通过localStorage实现一个事件处理程序。

假设我们有一个网页如下。对输入字段的任何更改都将触发事件,我们将新值保存到localStorage。 JSBin

<html ng-app="app">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  </head>
  <body ng-controller="Ctrl">
    <input type="text" ng-model="text"></input>
    <div id="console"></div>
    <script>
      var app = angular.module('app', []);
      app.controller('Ctrl', ["$scope", function ($scope) {
        $scope.$watch('text', function (newValue, oldValue) {
          var x = "nV: " + newValue;
          localStorage.setItem("messages", localStorage.getItem("messages") + "   " + x)
          debug(localStorage.getItem("messages"))
        }, false)
      }])

      function debug(msg) {
        document.getElementById("console").innerHTML += msg + "<br/>";
      }
    </script>
  </body>
</html>

我们有另一个网页听。它按setInterval扫描localStorage。它实际上是一个管道:几个消息可以存储在localStorage中,我们应该将它们全部处理,然后清空localStorageJSBin

<html>
  <body>
    <div id="console"></div>
    <script>
      var listen = setInterval(function () {
        var m = localStorage.getItem("messages");
        if ((m !== "") && (m !== undefined)) {
          localStorage.setItem("messages", "")
          treatMessages(m);
        }
      }, 100)

      function treatMessages(messages) {
        debug(messages)
      }

      function debug(msg) {
        document.getElementById("console").innerHTML += msg + "<br/>";
      }
    </script>
  </body>
</html>

但重要的是,我们应该确保接收方没有错过任何消息。不幸的是,目前情况并非如此,例如,我在输入字段中快速键入123456789,然后在接收器侧缺少12345。这可能是因为发送方在接收方读取localStorage之后和接收方清空localStorage之前生成了12345

所以有人知道如何解决这个问题吗?我们应该有localStorage的信号量还是有其他解决方法?

enter image description here

编辑1:我尝试按lockwaitfor添加信号量:the senderthe receiver,但仍然可能会错过消息。例如,以下示例中缺少123456。这并不奇怪,我认为这是因为当lockfree时,我们同时进入了2等待的回调,然后它搞砸了。

enter image description here

编辑2:我做了另一个应该更好的镜头,但我不知道为什么这两个页面无法对齐其localStorage值:the sender和{{3 }}

2 个答案:

答案 0 :(得分:1)

尝试较新的IndexedDB。 https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB。它更复杂/复杂。它现在得到广泛支持:http://caniuse.com/#search=indexeddb

我相信它可以解决您上面的问题(错过的消息),但没有changeEvent。我还认为,由于缓存,它无法在Mac上看到浏览器(WebKit)实例(例如Excel for Mac)的更改,但是应该可以跨标签工作。

答案 1 :(得分:0)

我建议使用localDataStorage为您触发事件,为每个键值添加,删除或更改。它甚至可以在单个页面/选项卡中报告这些事件!此实用程序可以透明地设置/获取以下任何“类型”:Array,Boolean,Date,Float,Integer,Null,Object或String(无需转换)。

[免责声明]我是该实用程序的作者[/ DISCLAIMER]

实例化实用程序后,以下代码段将允许您监视事件:

function localStorageChangeEvents( e ) {
    console.log(
        "timestamp: "     + e.detail.timestamp + " (" + new Date( e.detail.timestamp ) + ")" + "\n" +
        "key: "           + e.detail.key     + "\n" +
        "old value: "     + e.detail.oldval  + "\n" +
        "new value: "     + e.detail.newval  + "\n"
    );
};
document.addEventListener(
    "localDataStorage"
    , localStorageChangeEvents
    , false
);