문제

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.

다른 팁

Just more informations on one point:

JavaScript is often executed in multi-threaded environments.

On client-side

In addition to workers, each iframe, window tab, or opened window has its own thread all communicating with window messaging API or from which you can directly access to their document properties if there is no cross origin restrictions.

Some DOM/HTML5 APIs propose synchronous APIs and some people at W3C are working to make those synchronous version only usable from Web Workers, potentially only Dedicated Workers.

On server-side

If node.js run in JavaScript in a single thread by default, it can still generate other node processes with there own thread and communicate with them. It actually also provide some synchronous versions of its APIs.

Most of the other Server JS platforms like Wakanda, RingoJS, TeaJS, APE, SilkJS and others are multithreaded and can run JavaScript synchronously with synchronous APIs (Wakanda allows also to easily use async APIs either with the sync APIs or in async specific threads)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top