考虑到 javascript 在单个线程中执行,promise.all 有用吗? [英] Is promise.all useful given that javascript is executed in a single thread?

查看:16
本文介绍了考虑到 javascript 在单个线程中执行,promise.all 有用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

promise1.then(function(p1){var p2 = makePromise2();var p3 = makePromise3();var p4 = makePromise4();返回 [p2, p3, p4];}).all(承诺,功能(){console.log('所有承诺都已完成');}, 函数(原因){console.log('一个承诺被拒绝:' + reason.toString());});

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

解决方案

首先 - JavaScript 作为一种语言并没有说明并发性.事实上,在很多场景中,您都可以创建和运行多线程 JavaScript - WebWorkers 在网络中、节点中以及在您自己将 JS 引擎集成到现有应用程序中时.

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

虽然 JavaScript DOM 代码的执行是单线程的,但 I/O 操作实际上在不同的线程上运行,并且事件会通知 JavaScript 线程发生变化.有时,完全像 Windows 中的 IOCP(I/O 完成端口)一样使用操作系统工具进行异步并发.

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

//与所有var a = ["url1","url2","url3"].map(makeAjaxPromise);//进行 3 次 ajax 调用Promise.all(a).spread(function(res1,res2,res3){//Q.all with Qalert("一切都加载了!");});

这里同时进行了 3 个 ajax 调用.即使在这种情况下 JavaScript 在单个线程中运行 - 请求都是并行发出的,一旦请求完成,线程就会收到通知,使用事件循环"在事件完成时通知代码,进而解决承诺.

然而,当你这样做时

 makeAjaxPromise("url1").然后(makeAjaxPromise.bind(null,url2").then(makeAjaxPromise.bind(null,"url3").then(function(){alert("一切都加载了!");//这里不考虑获取数据});

它会发出一个请求,等待它完成,再发出一个请求,等待它,然后再发出第三个请求,然后才解决.

所以 - 第一种情况:

  • 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 必须等待更多,可能是三倍.

In, for example, kriskowal's Q, one can do something like:

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

Given that javascript executes in a single thread, does this have any benefit, performance or otherwise, over simply doing a series of then() calls?

解决方案

First of all - JavaScript as a language does not say anything about concurrency. In fact, in a lot of scenarios you can create and run multithreaded JavaScript - WebWorkers in the web, in node, and when integrating a JS engine in an existing app yourself.

In fact, there is nothing asynchronous in the JavaScript language (Until ES2015). However, in practice - host environments which are how JavaScript interacts with the world implement asynchronous APIs.

While execution of JavaScript DOM code is single threaded, I/O operations actually run on a different thread and events notify the JavaScript thread of changes. Sometimes, using an operating system facility for asynchronous concurrency completely like IOCP (I/O completion ports) in Windows.

Let's take AJAX for example. Let's say I have a list of URLs and I map each of them to an XHR call.

// 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!");
});

Here, 3 ajax calls are made at once. Even though JavaScript runs in a single thread in this case - the requests are all made in parallel, and the thread gets notified once they are complete using an "event loop" that notifies code when events completed which in turn resolves the promises.

However, when you do

 makeAjaxPromise("url1").
 then(makeAjaxPromise.bind(null,"url2").
 then(makeAjaxPromise.bind(null,"url3").then(function(){
      alert("Everything loaded!"); // disregarding getting the data here
 });

It'll make a single request, wait for it to complete, make another one, wait for it, make a third one only then and only then resolve.

So - first case:

  • JavaScript thread makes 3 DOM API calls
  • DOM API gets these calls and makes XHR requests, it yields control back to JavaScript immediately
  • When those requests are ready, it notifies JavaScript and it runs the handler if it is free to do so.

Second case

  • JavaScript thread makes a DOM API call.
  • DOM API gets call, makes an XHR request, yields control back to JavaScript.
  • When the first request is ready, JavaScript gets notified and it runs the next in line: -JavaScript thread makes a DOM API call.
  • DOM API gets call, makes an XHR request, yields control back to JavaScript.
  • When the second request is ready, JavaScript gets notified and it runs the next in line: -JavaScript thread makes a DOM API call.
  • DOM API gets call, makes an XHR request, yields control back to JavaScript.
  • When the thirdrequest is ready, JavaScript gets notified and it runs the next in line:
  • All three ready.

So in the second case, the requests are not made in parallel and JavaScript has to wait a lot more, possibly three times as much.

这篇关于考虑到 javascript 在单个线程中执行,promise.all 有用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆