例如,在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()调用?
答案 0 :(得分:17)
首先,JavaScript作为一种语言并没有提及并发性。实际上,在很多场景中,您可以创建和运行多线程JavaScript - Web中的WebWorkers,节点中以及自己在现有应用程序中集成JS引擎时。
事实上,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必须等待更多,可能是等待的三倍。
答案 1 :(得分:3)
关于一点的更多信息:
JavaScript通常在多线程环境中执行。
在客户端
除了工作者之外,每个iframe,窗口选项卡或打开的窗口都有自己的线程,它们都与窗口消息传递API进行通信,或者如果没有交叉源限制,您可以从中直接访问它们的文档属性。
一些DOM / HTML5 API提出了同步API,W3C的一些人正在努力使这些同步版本只能从Web Workers中使用,可能只有Dedicated Workers。
在服务器端
如果node.js默认在单个线程中运行JavaScript,它仍然可以生成具有自己的线程的其他节点进程并与它们通信。它实际上还提供了一些API的同步版本。
大多数其他服务器JS平台,如Wakanda,RingoJS,TeaJS,APE,SilkJS等都是多线程的,可以与同步API同步运行JavaScript(Wakanda还允许使用同步API或异步特定的API轻松使用异步API线程)