- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
tl;dr 我注意到在同一时间写入 localStorage 时浏览器之间的行为不一致。
要求:即使打开了多个选项卡,特定操作(刷新 OAuth session 的 POST 请求)也应该只执行一次。哪个选项卡执行操作并不重要。刷新的时间点源自 session 的到期时间,并且在所有选项卡中都完全相同。
方法:所有标签生成一个随机数,存储它并写入localStorage。然后他们读取 localStorage,如果两者相同,则允许选项卡执行操作。
let tab = Math.random();
localStorage.setItem('tab',tab);
if(JSON.parse(localStorage.getItem('tab')) === tab) {
console.log('aquired lock');
} else {
console.log('did not aquire lock');
}
JSFiddle - 为了测试您需要在两个选项卡中打开 fiddle 的行为,然后在两个选项卡中按运行。计算超时以在下一个完整的 10 秒执行。 (第二个 0、10、20、30、40、50)
预期:选项卡 A 和 B 将 localStorage['tab'] 设置为随机值,在检索该值时只有 一个 选项卡检索与其随机生成的值相同的值因此可以执行该操作。
结果:A 和 B 仍然检索它们自己生成的值。
我添加了一些超时让内存灰尘安顿下来:
let tab = Math.random();
localStorage.setItem('tab',tab);
setTimeout(function(){
if(JSON.parse(localStorage.getItem('tab')) === tab) {
console.log('aquired lock');
} else {
console.log('did not aquire lock');
}
}, 1000);
结果 (Firefox): 选项卡 A 检索选项卡 B 生成的值,反之亦然。因此不允许任何选项卡执行该操作。
这是我有点害怕的地方。我检查了完全相同的控制台时间戳和开发工具中的 localStorage,它在不同的选项卡中显示了不同的值。 (即使重新加载选项卡也确实在不同的选项卡中显示了不同的值。)
如果稍后写入值(例如通过控制台),所有选项卡都会相应地更新值。
结果(Chrome、Edge):只有一个选项卡按预期记录 aquired lock
。
是否有任何解释为什么 Firefox 可以在每个选项卡的 localStorage 中有不同的值?
我已经通过订阅 StorageEvent 解决了这个问题.具有最小随机数的选项卡将执行该操作。
使用的浏览器:
最佳答案
这是处理共享内存时相当标准的情况。出于性能原因,允许访问共享内存的每个线程保留自己的副本(“缓存”),直到/除非发生某种同步,此时必须将本地副本与共享副本协调。
旧存储规范 talked about在每个存储操作中获取一个存储互斥量:
Whenever the properties of a
localStorage
attribute'sStorage
object are to be examined, returned, set, or deleted, whether as part of a direct property access, when checking for the presence of a property, during property enumeration, when determining the number of properties present, or as part of the execution of any of the methods or attributes defined on theStorage
interface, the user agent must first obtain the storage mutex.
但该规范已被包含在 WHAT-WG“HTML”规范(比 HTML 多得多)的§11(“Web 存储”)中,并且每个操作都必须获取存储互斥锁的要求已被取消下降。 (我不知道为什么,但我猜是出于性能原因。)当前规范 says :
Warning: The
localStorage
attribute provides access to shared state. This specification does not define the interaction with other browsing contexts in a multiprocess user agent, and authors are encouraged to assume that there is no locking mechanism.
该规范也没有讨论跨浏览上下文的存储同步。这意味着实现可以自由优化。
用 modified version of your script 查看它,看起来 Firefox 通过为每个浏览上下文(选项卡)拥有本地存储的本地副本来优化它似乎基于 storage
更新来自其他上下文(选项卡)的事件。但是,如果两个选项卡都在 storage
之前设置值(为另一个选项卡生成 storage
事件)来自另一个选项卡的事件被处理,他们都得到并处理 storage
来自另一个的事件,更新为该值(另一个选项卡的值),导致您描述的行为。
旁注:写入持久存储的操作(如果您在完成所有这些操作后打开它,第三个选项卡会看到什么)似乎也是异步的,并且两个选项卡正在竞争看哪个最后写入(a最后一个写入其本地副本的比赛并不总是获胜!)。
当线程之间只有松散的同步并且没有锁定语义时,这实际上是线程之间共享内存所发生情况的大规模版本,规范不再需要锁定语义。
Chrome 似乎在进行锁定或类似操作。
关于javascript - 从多个选项卡同步写入 localStorage 时不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57089227/
我有这个代码 var myChart = new FusionCharts("../themes/clean/charts/hbullet.swf", "myChartId", "400", "75
既然写入是立即进行的(复制到内核缓冲区并返回),那么使用 io_submit 进行写入有什么好处? 事实上,它 (aio/io_submit) 看起来更糟,因为您必须在堆上分配写入缓冲区并且不能使用基
我正在使用 mootool 的 Request.JSON 从 Twitter 检索推文。收到它后,我将写入目标 div 的 .innerHTML 属性。当我在本地将其作为文件进行测试时,即 file:
最终,我想将 Vertica DB 中的数据抓取到 Spark 中,训练机器学习模型,进行预测,并将这些预测存储到另一个 Vertica DB 中。 当前的问题是确定流程最后部分的瓶颈:将 Spark
我使用 WEKA 库编写了一个 Java 程序, 训练分类算法 使用经过训练的算法对未标记的数据集运行预测 将结果写入 .csv 文件 问题在于它当前写出离散分类结果(即算法猜测一行属于哪个类别)。我
背景 - 我正在考虑使用 clickonce 通过 clickonce(通过网站)部署 WinForms 应用程序。相对简单的应用程序的要素是: - 它是一个可执行文件和一个数据库文件(sqlite)
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
我正在读取 JSON 文件,取出值并进行一些更改。 基本上我向数组添加了一些值。之后我想将其写回到文件中。当我将 JSONArray 写回文件时,会被写入字符串而不是 JSONArray 对象。怎样才
我为两个应用程序使用嵌入式数据库,其中一个是服务器,另一个是客户端。客户端应用程序。可以向服务器端发送获取数据请求以检索数据并显示在表格(或其他)中。问题是这样的:如何将获取的数据保存(写入)到页面文
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
从问题得出问题:找到所有 result = new ArrayList(); for (int i = 2; i >(i%8) & 0x1) == 0) { result.add(i
由于某种原因,它没有写入 CSV。谁能明白为什么它不写吗? def main(): list_of_emails = read_email_csv() #read input file, cr
关闭。 这个问题是 not reproducible or was caused by typos 。它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能在这里出现,
我目前正在开发一个保存和加载程序,但我无法获得正确的结果。 编写程序: #include #include #define FILENAME "Save" #define COUNT 6 type
import java.io.*; public class Main2 { public static void main(String[] args) throws Exception {
我需要使用预定义位置字符串“Office”从所有日历中检索所有 iOS 事件,然后将结果写入 NSLog 和 UITextView。 到目前为止,这是我的代码: #import "ViewCo
我正在尝试将 BOOL 值写入 PFInstallation 中的列,但会不停地崩溃: - (IBAction)pushSwitch:(id)sender { NSUserDefaults *push
我以前在学校学过一些简单的数据库编程,但现在我正在尝试学习最佳实践,因为我正在编写更复杂的应用程序。写入 MySQL 数据库并不难,但我想知道让分布式应用程序写入 Amazon EC2 上的远程数据库
是否可以写回到ResourceBundle?目前我正在使用 ResourceBundle 来存储信息,在运行时使用以下内容读取信息 while(ResourceBundle.getBundle("bu
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!