具有多个浏览器选项卡/窗口的主干.js 和本地存储覆盖数据

Posted

技术标签:

【中文标题】具有多个浏览器选项卡/窗口的主干.js 和本地存储覆盖数据【英文标题】:backbone.js and local storage with multiple browser tabs / windows overwrites data 【发布时间】:2012-06-11 05:58:51 【问题描述】:

只是一个关于将 Backbone.js 与 LocalStorage 结合使用的简短问题:

我在 LocalStorage 中存储了一个事物列表(主干集合)。当我的网站在多个浏览器窗口/选项卡中打开并且两个窗口中的用户都向列表中添加了一些内容时,一个窗口的更改将覆盖另一个窗口中所做的更改。

如果您想自己尝试,只需使用示例 Backbone.js Todo 应用:

    在两个浏览器标签中打开http://backbonejs.org/examples/todos/index.html 在第一个选项卡中添加一个项目“item1”,在第二个选项卡中添加一个“item2” 刷新两个标签:“item1”将消失,您将只剩下“item2”

有什么建议可以防止这种情况发生,有什么标准的方法来处理吗?

谢谢

【问题讨论】:

【参考方案1】:

这个问题是众所周知的并发丢失更新问题,请参阅Lost update in Concurrency control?。 为了您的理解,我可能会提出以下快速而肮脏的修复,文件backbone-localstorage.jsStore.prototype.save

save: function() 
    // reread data right before writing
    var store = localStorage.getItem(this.name);
    var data = (store && JSON.parse(store)) || ;
    // we may choose what is overwritten with what here
    _.extend(this.data, data);

    localStorage.setItem(this.name, JSON.stringify(this.data));

对于latest Github version of Backbone localStorage,我认为应该是这样的:

save: function() 
  var store = this.localStorage().getItem(this.name);
  var records = (store && store.split(",")) || [];
  var all = _.union(records, this.records);
  this.localStorage().setItem(this.name, all.join(","));

【讨论】:

谢谢!只是我需要的提示。我知道这是一种 hack,但它确实有效。 我编辑了您的回复以包含适用于最新 Github 版本的 Backbon localStorage 的代码。 我今天在公司遇到了这个问题。非常感谢您的快速修复!真的很有帮助!【参考方案2】:

您可能想改用 sessionStorage。 见http://en.wikipedia.org/wiki/Web_storage#Local_and_session_storage。

【讨论】:

这是正确答案。只有一个用于主干.js 的本地存储适配器 backbonejs.org/docs/backbone-localstorage.html 您必须编写自己的实现才能使用会话存储 对不起,我应该更清楚。我想要的是 localStorage,因为我需要在会话之间保留数据。仅以上面的 Todo 列表为例:您不希望在关闭选项卡或浏览器窗口时清除您的 todo 列表。下次您回到您的应用时,您希望它在那里。 想象一下你打开了两个窗口,填写了不同的数据,然后都关闭了,然后打开了一个新窗口。之前关闭的两个中的哪一个应该从其中获取数据?那么你需要完整的授权和身份验证。 不,我不想识别或验证任何用户。这是一个非常简单的案例。再次以 Todo 应用为例:假设您在两个浏览器选项卡中打开它。如果您在两个选项卡中添加待办事项,则不需要第一个或第二个选项卡的数据。显然你想要两者。如果您在两个选项卡中添加待办事项,您希望两个项目都存储在本地存储中,而不是稍后添加的项目覆盖第一个。【参考方案3】:

Yaroslav 关于在持久化新更改之前检查更改的评论是一种解决方案,但我的建议会有所不同。请记住,localStorage 在执行更改其保存的数据的操作时能够触发事件。绑定到这些事件并让每个选项卡监听这些更改并在发生后重新呈现视图。

然后,当我在一个选项卡中进行删除或添加并移至下一个选项卡时,它会收到一个事件并更改以反映另一个选项卡中发生的情况。我看到的选项卡之间不会有奇怪的差异。

您需要考虑确保我不会丢失正在添加的内容(例如,我开始为我的待办事项列表输入新条目),切换到另一个选项卡并删除某些内容,然后回来我希望看到该条目消失,但我部分键入的新项目应该仍然可供我使用。

【讨论】:

此方案用户体验更好。 这个解决方案在形式上看起来更正确,而且不会被黑客攻击,真的!但它有很多怪癖或缺乏对 IE、Safari 和 Chrome 的支持。刚刚试了一下,它在 FF 中运行良好,但在 Chrome 中却不是,这就是我使用上述 hack 的原因。

以上是关于具有多个浏览器选项卡/窗口的主干.js 和本地存储覆盖数据的主要内容,如果未能解决你的问题,请参考以下文章

具有多个连接到 https 站点的选项卡式浏览器窗口的电子应用程序

如何在javascript中检测浏览器选项卡是不是关闭或浏览器窗口

关闭所有选项卡时删除/清除本地存储[重复]

js跳转页面在新选项卡中打开

如何在关闭特定选项卡而不是在 Angular 2 中关闭浏览器时清除本地存储?

Blazor Server 如何跨多个选项卡和刷新保存数据