gpt4 book ai didi

javascript - 异步 Javascript 程序如何交互

转载 作者:可可西里 更新时间:2023-11-01 02:23:07 25 4
gpt4 key购买 nike

回到网络开发的早期,我学到了一些民间智慧,对于像这样的代码

<script src=".../program1.js"></script>
<script src=".../program2.js"></script>

浏览器会暂停,加载 javascript,编译,执行,移动到下一个 script 标签,然后重复。通过这种方式,浏览器将处理页面上的所有 javascript,并将其视为一个线性程序。

然而,在崭新的现代 javascript 世界中,我们通过 async 属性进行异步加载

<script src=".../program1.js" async></script>
<script src=".../program2.js" async></script>

据我所知,这是一件好事,因为现在浏览器不需要暂停、下载脚本和执行它。相反,它开始下载脚本,但会继续解析 DOM。即网页在等待 javascript 下载时不再阻塞。 (如果这不是真的,我将不胜感激。)

然而,不太清楚(也更难测试)的是这两个程序如何交互。它们似乎在同一个共享空间中运行(即,从用户空间的 Angular 来看,javascript 仍然是具有两个(全局、函数)范围的单线程)。但是,在我阅读的文档中,它们执行的顺序似乎定义不明确。

我已经通读了关于 Concurrency model and Event Loop 的 MDN 文章.虽然有趣且有用,但它并不能完全回答我的问题。据我所知,当浏览器加载 program1.jsprogram2.js 时,javascript 将向事件队列添加一条消息,该消息将作为 javascript 处理引擎通过事件循环运行。

我缺少的是 - 该消息说了什么?每个程序都有一条消息说“编译并执行所有这些javascript代码”吗?还是每个程序都会创建多条消息——在我看来可能类似于

  • 消息 1:从该程序中提取所有函数并编译它们
  • 消息 2:从此程序中提取全局范围内的所有语句和表达式
  • 消息 3-n:将每个语句和表达式添加为单独的队列消息以供稍后处理。

当浏览器正在处理 program1.js 但完成下载 program2.js 时会发生什么?每个程序的语句执行是否可能交错进行?

我意识到,作为客户端开发人员,这里的最佳实践是不依赖于全局范围并编写每个程序和函数,因此它的调用方式无关紧要,并且不会阻止其他人的代码。但是,我花了很多时间处理其他人的代码,其中一些代码表现不佳。我想了解幕后发生的事情,或者这是否是未定义且独立于引擎的行为,并且不会在实现之间排队。

最佳答案

有两篇文章从实际意义上说明了“async”和“defer”属性(我对浏览器内部结构很陌生):

从 2014 年开始,具有优秀+简单的图形: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

从 2016 年开始,为什么异步可能是一种反模式: http://calendar.perfplanet.com/2016/prefer-defer-over-async/

异步

对于您的问题,“异步”指示浏览器执行的操作是:

  1. 尽早开始下载此资源。
  2. 继续并随时并行下载其他资源。
  3. 但是一旦我的下载完成,就停止渲染并尽早开始执行我。

实际上“异步”仍然可以阻止渲染和后续执行,但它允许解析器继续工作直到执行开始。

多个异步脚本无法保证它们的执行顺序。取决于加载的速度。这使得像 RequireJS 这样的 AMD 系统可以定义依赖项和回调以异步加载资源,但将它们的执行排队,直到“全局”环境包含所有先决条件并且可以协商执行顺序(通过 rune 魔法)。

延迟

Defer 的行为是这样的:

  1. 尽早开始下载此资源。
  2. 继续并随时并行下载其他资源。
  3. 但是一旦我的下载完成,在解析器完成之前什么都不做。
  4. 现在按照它们被发现的顺序执行所有脚本。

一方面,“延迟”更快,因为它永远不会阻塞解析器或渲染。但是“延迟”可能会更慢,因为它必须等到管道畅通后才能执行。

听起来“异步”总是更好,但是如果您在具有快速连接的弱 CPU 手机上加载 2 MB 的 JS,您可能最终需要等待 10 秒才能执行,然后允许解析器完成渲染。使用“延迟”可以防止这种情况发生,但代价是您的交互层被延迟。

如果您谈论的是客户端/服务器或客户端应用程序,则区别会更加模糊。在后端繁重的应用程序(例如在服务器端处理渲染的 Magento)中使用 defer 可能更有益。

在完全客户端的应用程序中,在加载 JS 单体之前,您可能获得零内容,因此“延迟”实际上不会为您做任何事情,但如果您的整个应用程序是一个巨大的 JS,那么“异步”也不会捆绑在一起,没有什么可并行进行的。

关于javascript - 异步 Javascript 程序如何交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41170128/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com