JavaScript 是否为非阻塞生成线程 AJAX?

Does JavaScript spawn threads for non-blocking AJAX?

一般的看法是 JavaScript 本质上是单线程的,但它可以 运行 异步。我想知道像这样的单线程模型如何处理 AJAX 非阻塞请求?

假设在浏览器中触发了一个非阻塞 AJAX 请求,但没有立即得到响应。如果事件循环不断检查响应,执行不会被阻塞吗?当没有响应时,事件循环是否继续检查其状态和 're-adding' 任务到宏任务队列的后面?

据我了解,Node.js 会静默生成线程来处理 I/O 访问磁盘、数据库、网络套接字等操作。浏览器中的 JavaScript 是否会生成线程来处理 AJAX也是吗?

可以针对以下问题提出类似的问题:

var img = new Image();
img.onerror=function(){alert('error: '+this.src);}
img.onload=function(){alert('image loaded: '+this.src);}
img.src='path/to/image.jpg';

上面最后一行代码是否会导致产生一个额外的线程,因为该语句似乎是非阻塞的?

The general perception is that JavaScript is intrinsically single-threaded but it can run asynchronously.

Java确实指定了脚本¹,这样在 realm at any given time. (A realm is the global environment and its associated objects; e.g. a window/tab [on browsers].) You can have multiple active threads (in different windows, or via web workers), and they can talk to each other (via postMessage) or even share some memory (SharedArrayBuffer) 中只能执行一个线程,但它们不能同时访问同一个领域。保持领域有效的单线程避免了巨大范围的并发编程陷阱。

I wonder how a single-threaded model like this handles AJAX requests that are non-blocking?

JavaScript 一次只允许 JavaScript 环境中的一个线程并不意味着 host(浏览器)是单一的-线程。异步 ajax 请求被移交给浏览器的网络处理。

Java脚本基于 job queue(HTML5 规范称其为 任务队列,但 Java脚本规范提到了 "jobs"——它只是一个名称)。 Java脚本线程从队列中选取一个作业,运行完成该作业,然后选取下一个作业(如果有)。 (它比那复杂一点,但这是基本思想。)当线程正在 运行 一个作业时,没有其他线程可以 运行 同一领域中的另一个作业。

因此,当 ajax 请求完成(成功、超时等)时,浏览器(可能在非 Java 脚本线程上)将作业放入 Java脚本作业队列调用 ajax 回调。 Java脚本线程选择该作业并调用回调。

值得注意的是,这也正是它响应 其他 发生的事情(例如用户单击某些内容)所做的事情。

Lets say a non-blocking AJAX request is fired in a browser, but doesn't get a response immediately. If the event loop keeps checking for the response, doesn't the execution get blocked?

关键是线程 不会 持续检查是否有响应。该线程只监视作业队列。浏览器的网络处理程序处理网络请求的完成。


¹ 这在 ES2015 中明确表示,但在此之前的几年中,常见环境(浏览器,Node.js)就是这种情况。有 JavaScript 环境允许在一个领域中使用多个线程(如 Rhino,运行ning JavaScript on the Java VM),但它们被认为不够重要为了防止 ES2015 添加此要求,这样做允许围绕几个新功能定义精确的语义,如果可能的话,这些新功能本来会更加复杂,同时在线程主题上保持沉默。