【问题标题】:Multithreading with javascript promises带有 javascript 承诺的多线程
【发布时间】:2022-02-06 23:08:54
【问题描述】:

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

那么它如何使用 PromisePool 管理并发?

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

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

【问题讨论】:

  • 你在说什么 PromisePool?
  • 是的,您代码中的两个then 回调将彼此同步运行。

标签: javascript promise


【解决方案1】:

Javascript 是单线程的吧?

没有。这是一种常见的过度简化。

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

一般来说,你所有的 JavaScript 都会在那个事件循环上运行,所以一次只能运行一个 JS。

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

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

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


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

我当前的实现使用带有awaitfor 循环,因此一次只处理一个文件以获取元数据。

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

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

【讨论】:

    【解决方案2】:

    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);
     })();
    

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

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

    【讨论】:

    • 谢谢,这两个异步函数可以更新 DOM 吗?如果是这样,由于多个异步更新 DOM,DOM 是否有可能进入不一致的非确定性状态?
    • @TheWommies 是的,也不是。
    猜你喜欢
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 2017-10-04
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多