2.8. Promise.all

最后更新于:2022-04-01 21:10:44

[`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 `.then` 方法。 前面我们看到的批量获得若干XHR的请求结果的例子,使用 [`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 的话代码会非常简单。 之前例子中的 `getURL` 返回了一个promise对象,它封装了XHR通信的实现。 向 `Promise.all` 传递一个由封装了XHR通信的promise对象数组的话,则只有在全部的XHR通信完成之后(变为FulFilled或Rejected状态)之后,才会调用 `.then` 方法。 promise-all-xhr.js ~~~ function getURL(URL) { return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(new Error(req.statusText)); } }; req.onerror = function () { reject(new Error(req.statusText)); }; req.send(); }); } var request = { comment: function getComment() { return getURL('http://azu.github.io/promises-book/json/comment.json').then(JSON.parse); }, people: function getPeople() { return getURL('http://azu.github.io/promises-book/json/people.json').then(JSON.parse); } }; function main() { return Promise.all([request.comment(), request.people()]); } // 运行示例 main().then(function (value) { console.log(value); }).catch(function(error){ console.log(error); }); ~~~ 这个例子的执行方法和 [前面的例子](http://liubin.github.io/promises-book/#xhr-promise.js) 一样。 不过[`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 在以下几点和之前的例子有所不同。 * main中的处理流程显得非常清晰 * Promise.all 接收 promise对象组成的数组作为参数 ~~~ Promise.all([request.comment(), request.people()]); ~~~ 在上面的代码中,`request.comment()` 和 `request.people()` 会同时开始执行,而且每个promise的结果(resolve或reject时传递的参数值),和传递给 [`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 的promise数组的顺序是一致的。 也就是说,这时候 `.then` 得到的promise数组的执行结果的顺序是固定的,即 [comment, people]。 ~~~ main().then(function (results) { console.log(results); // 按照[comment, people]的顺序 }); ~~~ 如果像下面那样使用一个计时器来计算一下程序执行时间的话,那么就可以非常清楚的知道传递给 [`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 的promise数组是同时开始执行的。 promise-all-timer.js ~~~ // `delay`毫秒后执行resolve function timerPromisefy(delay) { return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } var startDate = Date.now(); // 所有promise变为resolve后程序退出 Promise.all([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (values) { console.log(Date.now() - startDate + 'ms'); // 約128ms console.log(values); // [1,32,64,128] }); ~~~ `timerPromisefy` 会每隔一定时间(通过参数指定)之后,返回一个promise对象,状态为FulFilled,其状态值为传给 `timerPromisefy` 的参数。 而传给 `Promise.all` 的则是由上述promise组成的数组。 ~~~ var promises = [ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]; ~~~ 这时候,每隔1, 32, 64, 128 ms都会有一个promise发生 `resolve` 行为。 也就是说,这个promise对象数组中所有promise都变为resolve状态的话,至少需要128ms。实际我们计算一下[`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 的执行时间的话,它确实是消耗了128ms的时间。 从上述结果可以看出,传递给 [`Promise.all`](http://liubin.github.io/promises-book/#Promise.all) 的promise并不是一个个的顺序执行的,而是同时开始、并行执行的。 > 如果这些promise全部串行处理的话,那么需要 等待1ms → 等待32ms → 等待64ms → 等待128ms ,全部执行完毕需要225ms的时间。 > 要想了解更多关于如何使用Promise进行串行处理的内容,可以参考第4章的[Promise中的串行处理](http://liubin.github.io/promises-book/#promise-sequence)中的介绍。
';