JavaScript Promise 的多线程处理

5

刚学习Promise。Javascript是单线程的对吧?那么使用fetch API进行http请求时,这一切都发生在一个线程中吗?

那PromisePool如何管理并发呢?

var p = Promise(...)
p.then(
...//stuff1
)
p.then(
//stuff2
)

那么这两个函数不能在多个线程上运行,对吧?只能在一个线程中运行吗?


你在谈论哪个 PromisePool? - Bergi
是的,您代码中的两个 then 回调将会同步依次执行。 - Bergi
2个回答

8
JavaScript是单线程的,对吗? 不是。这是一个常见的过度简化。
JavaScript运行一个主事件循环,一次只能执行一件事情。
通常,所有的JavaScript都将在一个事件循环中运行,因此一次只会运行一段JS代码。
但是,许多JavaScript函数调用的代码并不是JavaScript。例如,在浏览器中使用fetch,负责发起HTTP请求的是浏览器,在主事件循环之外处理请求,因此可以在等待响应的同时继续运行JS程序的其他任务。
Web Workers(浏览器)和Worker Threads(Node.js)是允许您将JS代码移出主事件循环的工具。
这些可以使用线程实现。
我有一些代码在文件系统中搜索音频文件,然后提取它们的元数据。一旦收集了所有的元数据,就会传递给进一步的处理。
我的当前实现使用for循环和await,以便一次只处理一个文件的元数据。
我的第一次尝试是并行处理,并尝试同时读取数百个音频文件,这时候消耗了我系统上所有的RAM。
我可以切换到Promise Pool,每次读取4个文件(每个CPU核心1个),以兼顾两全。

5
JavaScript是单线程的,对吗?
是的,一段JavaScript代码始终在一个代理(agent)中运行,并且一个代理只能同时执行一个函数。
那么当它使用fetch API进行HTTP请求时,这一切都发生在一个线程中吗?
不完全是这样。虽然您的JavaScript代码不能与其他JavaScript代码并行运行,但浏览器可以并行执行其他事情(例如呈现页面、垃圾回收等),包括为您执行请求。一旦响应返回,结果就会通过解析Promise传递回JavaScript。
它如何管理并发性?
虽然两个函数不能同时运行,但两个异步函数(或Promise链)可以,因为它们由多个执行单元组成,一旦其中一个完成,另一个就可以接管:
 (async function first() {
    await undefined;
    console.log(2);
    await undefined;
    console.log(4);
 })();
 (async function second() {
    console.log(1);
    await undefined;
    console.log(3);
 })();

JavaScript确实具有某种形式的并发性,但仅限于函数级别(或异步函数中的块),而不是单个指令级别。

要实现真正的并行执行,您需要使用多个代理(WebWorkers、ServiceWorkers),它们也可以以有限的方式共享内存。


谢谢,这两个异步函数能更新DOM吗?如果可以,由于多个异步更新DOM,DOM是否有可能进入不一致的非确定性状态? - TheWommies
@TheWommies 是的,也不是。 - Jonas Wilms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接