使用 JavaScript Promise 实现多线程

The*_*ies 6 javascript promise

只是学习承诺。JavaScript 是单线程的吗?那么当它使用 fetch api 发出 http 请求时,这一切都发生在一个线程中吗?

那么它如何管理 PromisePool 的并发呢?

var p = Promise(...)
p.then(
...//stuff1
)
p.then(
//stuff2
)
Run Code Online (Sandbox Code Playgroud)

那么上面的两个不能在多线程上运行,对吗?仅在一个线程中?谢谢

Que*_*tin 9

JavaScript 是单线程的吗?

不,这是一种常见的过度简化。

JavaScript 运行一个主事件循环,它一次只能做一件事。

一般来说,所有 JavaScript 都会在该事件循环上运行,因此一次只会运行一段 JS。

然而,许多 JavaScript 函数调用的代码不是 JavaScript。以fetch浏览器为例。发出 HTTP 请求的责任由浏览器在主事件循环之外负责,因此它可以发出多个请求并等待响应,同时 JS 程序继续运行其他任务。

Web Workers(浏览器)和 Worker Threads (Node.js) 是让您将 JS 代码移出主事件循环的工具。

这些可以使用线程来实现。


我有一些代码可以在文件系统中搜索音频文件,然后从中提取元数据。收集所有元数据后,会将其传递以进行进一步处理。

我当前的实现使用for循环,await以便一次只处理一个文件的元数据。

我的第一次尝试尝试并行执行它们,并尝试同时读取数百个音频文件,耗尽了系统上的所有 RAM。

例如,我可以切换到 Promise Pool 并一次读取 4 个文件(每个 CPU 核心 1 个),以获得两全其美的效果。


Jon*_*lms 5

JavaScript 是单线程的吗?

是的,一段 JavaScript 代码总是在一个代理中运行,并且一个代理一次只能执行一个函数。

那么当它使用 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);
 })();
Run Code Online (Sandbox Code Playgroud)

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

为了获得真正的并行执行,您需要多个代理(WebWorkers、ServiceWorkers),然后它们还可以以有限的方式共享内存。