Javascript 具有多个选项卡的localstorage和setInterval()
我们在Javascript 具有多个选项卡的localstorage和setInterval(),javascript,Javascript,我们在localstorage中存储了一些数据,并使用window.setInterval()每分钟定期更新一次。在这段时间内,我们不断地读取和写入数据 由于使用了setInterval(),多个选项卡可以同时修改localstorage中的数据,是否会出现并发问题 编辑1:详细解释场景: 每个选项卡都针对一个键(例如xyz)向localstorage写入一些数据,并且运行的javascript中存在的setInterval(),不断检查xyz键数据。如果键上存在一些数据,则setInterv
localstorage
中存储了一些数据,并使用window.setInterval()
每分钟定期更新一次。在这段时间内,我们不断地读取和写入数据
由于使用了setInterval()
,多个选项卡可以同时修改localstorage
中的数据,是否会出现并发问题
编辑1:详细解释场景: 每个选项卡都针对一个键(例如
xyz
)向localstorage
写入一些数据,并且运行的javascript中存在的setInterval()
,不断检查xyz
键数据。如果键上存在一些数据,则setInterval
回调将其发送到后端。运行相同脚本的每个选项卡将读取xyz
键,并在执行某些逻辑后将一些数据附加到现有值
我怀疑是否会出现并发问题,例如一个选项卡可能正在读取
xyz
键并向本地存储添加数据,而另一个选项卡可能正在同时执行相同的操作。现在两者都将尝试同时发送数据,因此我可能会在后端接收相同的数据2次。编辑后添加:还有一种可能性,您可以尝试找出您的哪个页面/选项卡处于活动状态(您的页面),然后仅在活动选项卡上激活计时器,从而降低发生并发的可能性。
下面是用于可见性检查的api
由于多个选项卡可以同时修改本地存储中的数据,所以使用SetInterval()可能会出现并发问题吗
这有两个方面:
getItem
/setItem
(及其访问器等价物)是原子的吗getItem
/setItem
调用的不同选项卡/窗口能否将这些调用交错getItem
/setItem
将是原子的-也就是说,如果两个线程同时调用getItem
/setItem
,那么您获取/设置的数据不会被破坏
Re#2,我认为没有任何保证,没有。如果每个选项卡/窗口都有自己的线程,那么理论上,其中两个线程可以同时进入执行这些更新的代码块。有时,选项卡/窗口共享一个线程,在这种情况下,您是安全的,但是
我会避免在localStorage
中有大量需要以协调方式更新的不同条目。相反,我会使用一个带有结构的条目。我通常使用JSON来实现这一点。因此,获取数据的过程如下所示:
let data = JSON.parse(localStorage.getItem("the-data")) || {/*...default structure here...*/};
localStorage.setItem("the-data", JSON.stringify(data));
保存它看起来是这样的:
let data = JSON.parse(localStorage.getItem("the-data")) || {/*...default structure here...*/};
localStorage.setItem("the-data", JSON.stringify(data));
所以你可以
let data = JSON.parse(localStorage.getItem("the-data")) || {/*...default structure here...*/};
// ...modify the various parts of `data`...
localStorage.setItem("the-data", JSON.stringify(data));
然后在线程之间留下一个简单的竞争(最后一个写WINS),但是存储的数据将是一致的。在我看来,这确实取决于你认为的“并发问题”。
就编写而言,我不认为您会有任何问题,浏览器会很好地管理应该在何时向localstorage
写入什么内容。在此过程中,您的数据不会被损坏
对于读取,我相信当您从Tab1读取时会遇到问题,但最后一次写入是从Tab2进行的。当然,除了他们无权访问
localStorage
。是的,它无权访问它,但您可以在webworker和localStorage之间建立一些代理,这真的取决于您将如何做。编辑为更好的答案谢谢您的回答和建议。因为window.setInterval()是一个asyn函数,它在事件队列中等待,所以不应该存在任何并发问题。原始数据从何而来?来自ajax呼叫?@MisterJojo-这有什么关系?问题是关于读取和写入localStorage
@DeepakKumar-为什么存储由setInterval
回调处理,而不是在进行更改时由选项卡处理?另外,像Thomas一样,我将向您指出事件:如果您有选项卡A、B和C,并且它们都订阅了localStorage
上的storage
(它们来自同一来源),那么当选项卡B(例如)写入localStorage
时,选项卡A和C将接收storage
事件。这似乎与你在做什么有关(但我仍然不明白你在做什么)。谢谢你的回答,我编辑了这个问题以了解更多细节。在这种情况下,浏览器是否为两个不同的选项卡维护了两个回调队列?@DeepakKumar-正如我前面所说,每个窗口/选项卡始终有一个单独的回调队列。问题是是否有一个线程为这些选项卡上的队列提供服务,或者每个选项卡都有自己的线程,在后一种情况下,这意味着什么——我在回答中提到了这一点。我非常同意@t.J.Crowder:D@T.J.Crowder根据这个博客,跨多个选项卡的域将有一个线程,这意味着一个队列@DeepakKumar——正如我在评论和回答中至少说过三次的那样:每个选项卡/窗口都有自己的队列。正如我至少说过两次的:选项卡/窗口可以共享一个线程。然后,该线程必须在为每个队列提供服务之间来回运行。