我是否需要关心异步 Javascript 的竞争条件?

2024-05-11

假设我加载了一些我知道在将来某个时候会调用的 Flash 影片window.flashReady并将设置window.flashReadyTriggered = true.

现在我有一个代码块,我想在闪存准备好时执行它。我希望它立即执行,如果window.flashReady已经被调用,我想把它作为回调window.flashReady如果尚未被调用。天真的方法是这样的:

if(window.flashReadyTriggered) {
  block();
} else {
  window.flashReady = block;
}

所以我基于此的担忧是if条件评估为false,但之前block()可以执行,window.flashReady由外部闪光灯触发。最后,block从未被调用过。

是否有更好的设计模式来实现我想要的更高级别的目标(例如,手动调用flashReady打回来)?如果没有,我安全吗?或者我还应该做其他事情吗?


所有 Javascript 事件处理程序脚本均由一个主事件队列系统处理。这意味着事件处理程序一次运行一个事件处理程序,并且一个事件处理程序会运行直至完成,然后下一个准备就绪的事件处理程序才会开始运行。因此,Javascript 中不存在在多线程语言中会出现的典型竞争条件,在多线程语言中,该语言的多个线程可以同时运行(或时间切片)并在访问变量时产生实时冲突。

JavaScript 中的任何单个执行线程都会在下一个线程开始之前运行完成。这就是 JavaScript 的工作原理。从事件队列中提取事件,然后开始运行代码来处理该事件。该代码自行运行,直到将控制权返回给系统,然后系统将从事件队列中提取下一个事件并运行该代码,直到将控制权返回给系统。

因此,由两个同时执行的线程引起的典型竞争条件在 Javascript 中不会发生。

这包括所有形式的 Javascript 事件,包括:用户事件(鼠标、按键等)、计时器事件、网络事件(ajax 回调)等...

在 Javascript 中真正可以进行多线程处理的唯一地方是使用HTML5 网络工作者 http://blogs.msdn.com/b/davrous/archive/2011/07/15/introduction-to-the-html5-web-workers-the-javascript-multithreading-approach.aspx or 工作线程 https://nodejs.org/api/worker_threads.html(在node.js中),但它们与常规javascript非常隔离(它们只能通过消息传递与常规javascript通信)并且根本无法操作DOM并且必须有自己的脚本和命名空间等......


虽然从技术上讲我不会将其称为竞争条件,但 Javascript 中存在一些情况,因为它的一些异步操作可能会同时执行两个或多个异步操作(实际上并未执行 Javascript,但底层异步操作是同时运行本机代码),并且每个操作相对于其他操作何时完成可能是不可预测的。这会造成时间的不确定性(如果操作的相对时间对您的代码很重要),从而导致您必须手动编码。您可能需要对操作进行排序,以便一个操作运行,然后您实际上等待它完成,然后再开始下一个操作。或者,您可以启动所有三个操作,然后使用一些代码来收集所有三个结果,当它们全部准备好时,您的代码就会继续。

在现代 Javascript 中,promise 通常用于管理这些类型的异步操作。

因此,如果您有三个异步操作,每个操作都返回一个承诺(例如从数据库读取、从另一个服务器获取请求等),您可以像这样手动排序:

a().then(b).then(c).then(result => {
    // result here
}).catch(err => {
    // error here
});

或者,如果您希望它们全部一起运行(全部同时飞行)并且只知道它们何时完成,您可以这样做:

Promise.all([a(), b(), c()])..then(results => {
    // results here
}).catch(err => {
    // error here
});

虽然我不会将这些竞争条件称为竞争条件,但它们属于设计代码以控制不确定排序的同一个通用系列。


在浏览器中的某些情况下可能会出现一种特殊情况。这并不是真正的竞争条件,但如果您使用大量具有临时状态的全局变量,则可能需要注意。当您自己的代码导致另一个事件发生时,浏览器有时会同步调用该事件处理程序,而不是等到当前执行线程完成。一个例子是:

  1. click
  2. 单击事件处理程序将焦点更改为另一个字段
  3. 另一个字段有一个 onfocus 事件处理程序
  4. 浏览器立即调用 onfocus 事件处理程序
  5. onfocus 事件处理程序运行
  6. 单击事件处理程序的其余部分运行(在 .focus() 调用之后)

从技术上讲,这不是竞争条件,因为 onfocus 事件处理程序何时执行(在.focus()称呼)。但是,它可能会造成一种情况,即一个事件处理程序运行,而另一个事件处理程序正在执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我是否需要关心异步 Javascript 的竞争条件? 的相关文章

随机推荐

  • 使用查询选择器从 VBA 中抓取

    我使用了该网站的代码来提取数据site https bazashifer ru proflist profnastil Option Explicit Public Sub GetInfo Dim sResponse As String i
  • 使用 Mail_Mime 发送附件到 GMail,收到“noname”附件

    我有一个非常简单的网站表单 可以包含附件 它使用 gmail 的 smtp 发送到 gmail 地址 一切工作都很好 除了文件以 noname 形式到达 没有文件名或扩展名 如果您下载附件并使用正确的文件名重命名它 则该文件可以正常打开 我
  • 输入字符串的格式不正确

    下面的代码产生一个错误 指出我的输入字符串的格式不正确 为什么 private void button7 Click object sender EventArgs e string uriAddTagtoGroup string Form
  • 使用 fread 导入数据后所有列均作为字符

    我导入了一个 CSV 文件 包含文本列和数字列 x lt fread myfile csv header TRUE verbose T na strings c null null 但导入后 当我运行summary x 时 所有列都被视为字
  • 如何知道生成的序列最多是一定长度

    我想知道生成的序列是否少于 2 个条目 gt gt gt def sequence for i in xrange secret yield i 我的低效方法是创建一个列表 并测量其长度 gt gt gt secret 5 gt gt gt
  • 使用 PassportJS 和 Connect for NodeJS 对 Facebook 用户进行身份验证

    我正在尝试使用 connect 将 Passport 集成到我的 NodeJS 服务器中 但似乎无法正确执行 所有指南 示例都使用expressJS 因此我尽力重新格式化代码以与我的代码一起使用 但我似乎无法让它工作 相关部分写在下面 有人
  • 如何在chartjs中绘制多个时间序列,其中每个时间序列都有不同的时间

    例如 我有两个时间序列 s1 2017 01 06 18 39 30 100 2017 01 07 18 39 28 101 and s2 2017 01 07 18 00 00 90 2017 01 08 18 00 00 105 我想在
  • 如何从 Java 中的 String 获取类引用?

    如果我需要返回一个基于字符串实例化的类 例如 从 JSON 创建逻辑 应该如何编写 我最初的想法是一个 switch 但在 Android 框架的 Java 版本中 看起来 switch 语句不允许使用字符串 接下来的想法是 HashMap
  • iOS - 检测应用程序是否正在从 Xcode 运行 [重复]

    这个问题在这里已经有答案了 我试图根据代码是否通过 USB Xcode 调试 运行或在从应用程序商店下载的生产模式 发布 运行来启用 禁用部分代码 我知道检查它是否正在运行DEBUG or RELEASE像这样的模式 ifdef DEBUG
  • 内存不一致与线程交错有何不同?

    我正在编写一个多线程程序 正在研究是否应该使用volatile对于我的布尔标志 关于并发性的文档 oracle Trail 没有解释任何关于memory consistency errors以外 当不同的线程有内存一致性错误时 就会发生内存
  • 如何设计具有相互依赖的测试的 Specs2 数据库测试?

    有没有一些首选的方法来设计Specs2 http etorreborre github com specs2 测试 有很多测试取决于之前测试的结果 下面 您将找到我当前的测试套件 我不喜欢var位于测试片段之间 不过 它们是 需要的 因为某
  • Next JS - 源代码中缺少元标签

    我安装了多个元标记 例如标题 描述 关键字等 但是 它没有在查看源代码中显示这些标签 因此 Facebook 共享卡无法正常工作 我已经安装了og标签 但在 Facebook 上似乎找不到它们Scraper或我的查看来源 然而 它填充在客户
  • Scala 中奇怪的类型不匹配

    我希望这个问题还没有在其他地方得到解答 在这里没有找到答案 在我的本地化系统中 我有一个名为 Language 的类 class Language val name String dict HashMap String String def
  • 在 D3 中在外部加载的 svg 图形上绘图

    我已经从 svg 文件加载了外部图形 我想尝试在其上绘图 但不知道如何操作 我的简单 d3 代码在这里
  • 使用 oledb 在同一个 Excel 工作表上写入多个表

    我正在创建 excel 文件XML编写器 https msdn microsoft com en us library system xml xmlwriter v vs 110 aspx由于 xml 属性和文件类型电子表格 它的文件太大
  • 如何正则表达式字符串

    是否可以使用正则表达式检查 完整的字符串是数字AND 第一个字符是 7 或 8 那么字符串的完整长度必须是 11OR 第一个字符是 1 那么字符串的完整长度必须是 10 OR第一个字符是 0 然后是字符串的完整长度 必须是 18 AND 字
  • MongoDB C# 驱动程序“找不到光标”

    我有一个相当密集的操作MongoCursor循环运行几个小时 在通过 c 驱动程序运行的 vb net 应用程序上 我不太确定是什么导致了它 但一段时间后我遇到了异常 Cursor not found 这可能是由于游标超时造成的 有什么办法
  • 选择早于的时间戳

    我如何从数据库中选择超过 12 小时的项目 我使用时间戳列来存储时间 但我认为我不需要年 月 日 只需要小时 我有类似的东西 但它不起作用 没有错误 只是从表中返回所有数据 sql SELECT FROM Y WHERE X and tim
  • 如何在没有清单的情况下启用视觉样式

    根据docs http msdn microsoft com en us library bb773187 aspx 如果您希望应用程序使用 ComCtl32 dll 版本 6 则必须添加应用程序清单或编译器指令指定应使用版本 6 如果可用
  • 我是否需要关心异步 Javascript 的竞争条件?

    假设我加载了一些我知道在将来某个时候会调用的 Flash 影片window flashReady并将设置window flashReadyTriggered true 现在我有一个代码块 我想在闪存准备好时执行它 我希望它立即执行 如果wi