是 promise.all 有用的,因为 javascript 是在单个线程中执行的

Is promise.all useful given that javascript is executed in a single thread?

本文关键字:单个 线程 执行 因为 promise all 有用 javascript      更新时间:2023-09-26
例如

,在kriskowal的Q中,可以执行以下操作:

promise1.then(function(p1){
  var p2 = makePromise2();
  var p3 = makePromise3();
  var p4 = makePromise4();
  return [p2, p3, p4];
})
.all(promises, function(){
  console.log('all promises fulfilled');
}, function(reason){
  console.log('a promise was rejected: ' + reason.toString());
});

鉴于 javascript 在单个线程中执行,与简单地执行一系列 then() 调用相比,这有什么好处、性能或其他方面吗?

首先,JavaScript 作为一种语言并没有说任何关于并发性的事情。事实上,在很多场景中,你可以在 Web、节点中以及自己在现有应用程序中集成 JS 引擎时创建和运行多线程 JavaScript - WebWorkers。

事实上,JavaScript 语言中没有任何异步(直到 ES2015)。然而,在实践中 - JavaScript与世界交互的主机环境实现了异步API。

虽然 JavaScript DOM 代码的执行是单线程的,但 I/O 操作实际上在不同的线程上运行,事件会通知 JavaScript 线程更改。有时,使用操作系统工具进行异步并发完全类似于 Windows 中的 IOCP(I/O 完成端口)。

让我们以 AJAX 为例。假设我有一个 URL 列表,我将每个 URL 映射到 XHR 调用。

// with all
var a = ["url1","url2","url3"].map(makeAjaxPromise); // make 3 ajax calls
Promise.all(a).spread(function(res1,res2,res3){ // Q.all with Q
     alert("Everything loaded!");
});

在这里,一次进行 3 个 ajax 调用。即使 JavaScript 在这种情况下在单个线程中运行 - 请求都是并行发出的,并且线程在完成后使用"事件循环"收到通知,该循环在事件完成时通知代码,从而解析承诺。

但是,当您这样做时

 makeAjaxPromise("url1").
 then(makeAjaxPromise.bind(null,"url2").
 then(makeAjaxPromise.bind(null,"url3").then(function(){
      alert("Everything loaded!"); // disregarding getting the data here
 });
它会发出一个请求,等待它完成,发出

另一个请求,等待它,然后才发出第三个请求,然后才解决。

所以 - 第一种情况:

  • JavaScript 线程进行 3 次 DOM API 调用
  • DOM API 获取这些调用并发出 XHR 请求,它会立即将控制权交还给 JavaScript
  • 当这些请求准备就绪时,它会通知 JavaScript,并在有空的情况下运行处理程序。

第二种情况

  • JavaScript 线程进行 DOM API 调用。
  • DOM API 接收调用,发出 XHR 请求,将控制权交还给 JavaScript。
  • 当第一个请求准备就绪时,JavaScript 会收到通知,并运行下一个请求:JavaScript 线程进行 DOM API 调用。
  • DOM API 接收调用,发出 XHR 请求,将控制权交还给 JavaScript。
  • 当第二个请求准备就绪时,JavaScript 会收到通知,并运行下一行:JavaScript 线程进行 DOM API 调用。
  • DOM API 接收调用,发出 XHR 请求,将控制权交还给 JavaScript。
  • 当第三个请求准备就绪时,JavaScript 会收到通知,并运行下一行:
  • 三个都准备好了。

因此,在第二种情况下,请求不是并行发出的,JavaScript 必须等待更多,可能是三倍。

只是关于一点的更多信息:

JavaScript 通常在多线程环境中执行。

在客户端

除了工作线程之外,每个 iframe、窗口选项卡或打开的窗口都有自己的线程,这些线程都与窗口消息传递 API 通信,或者如果没有跨源限制,你可以从中直接访问其文档属性。

一些 DOM/HTML5 API 提出了同步 API,W3C 的一些人正在努力使这些同步版本只能从 Web Worker 使用,可能只能从专用 Worker 使用。

在服务器端

如果 node.js 默认在单个线程中运行在 JavaScript 中,它仍然可以生成具有自己的线程的其他节点进程并与之通信。它实际上还提供了其API的一些同步版本。

大多数其他服务器JS平台,如Wakanda,RingoJS,TeaJS,APE,SilkJS等都是多线程的,可以与同步API同步运行JavaScript(Wakanda还允许在同步API或异步特定线程中轻松使用异步API)