1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
---
title: Promise.all()
slug: Web/JavaScript/Reference/Global_Objects/Promise/all
tags:
- AJAX
- Async-Await
- Fetch
- Promise
- Promise.all()
- Promise.race()
- promise.all
translation_of: Web/JavaScript/Reference/Global_Objects/Promise/all
---
<div>{{JSRef}}</div>
<p>Promise.all() 方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,并且只返回一个{{jsxref("Promise")}}实例, 那个输入的所有promise的resolve回调的结果是一个数组。这个{{jsxref("Promise")}}的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。</p>
<div>{{EmbedInteractiveExample("pages/js/promise-all.html")}}</div>
<h2 id="语法">语法</h2>
<pre class="syntaxbox"><var>Promise.all(iterable)</var>;</pre>
<h3 id="参数">参数</h3>
<dl>
<dt>iterable</dt>
<dd>一个<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol">可迭代</a>对象,如 {{jsxref("Array")}} 或 {{jsxref("String")}}。</dd>
</dl>
<h3 id="返回值">返回值</h3>
<ul>
<li>如果传入的参数是一个空的可迭代对象,则返回一个<strong>已完成(already resolved)</strong>状态的 {{jsxref("Promise")}}。</li>
<li>如果传入的参数不包含任何 <code>promise</code>,则返回一个<strong>异步完成(asynchronously resolved)</strong> {{jsxref("Promise")}}。注意:Google Chrome 58 在这种情况下返回一个<strong>已完成(already resolved)</strong>状态的 {{jsxref("Promise")}}。</li>
<li>其它情况下返回一个<strong>处理中(pending)</strong>的{{jsxref("Promise")}}。这个返回的 <code>promise</code> 之后会在所有的 <code>promise</code> 都完成或有一个 <code>promise</code> 失败时<strong>异步</strong>地变为完成或失败。 见下方关于“Promise.all 的异步或同步”示例。返回值将会按照参数内的 <code>promise</code> 顺序排列,而不是由调用 <code>promise</code> 的完成顺序决定。</li>
</ul>
<h2 id="说明">说明</h2>
<p>此方法在集合多个 <code>promise</code> 的返回结果时很有用。</p>
<p>完成(Fulfillment):<br>
如果传入的可迭代对象为空,<code>Promise.all</code> 会同步地返回一个已完成(resolved)状态的<code>promise</code>。<br>
如果所有传入的 <code>promise</code> 都变为完成状态,或者传入的可迭代对象内没有 <code>promise</code>,<code>Promise.all</code> 返回的 <code>promise</code> 异步地变为完成。<br>
在任何情况下,<code>Promise.all</code> 返回的 <code>promise</code> 的完成状态的结果都是一个数组,它包含所有的传入迭代参数对象的值(也包括非 <code>promise</code> 值)。</p>
<p>失败/拒绝(Rejection):<br>
如果传入的 <code>promise</code> 中有一个失败(rejected),<code>Promise.all</code> 异步地将失败的那个结果给失败状态的回调函数,而不管其它 <code>promise</code> 是否完成。</p>
<h2 id="示例">示例</h2>
<h3 id="Promise.all_的使用"><code>Promise.all</code> 的使用</h3>
<p><code>Promise.all</code> 等待所有都完成(或第一个失败)。</p>
<pre class="brush: js">var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([p1, p2, p3]).then(values => {
console.log(values); // [3, 1337, "foo"]
});</pre>
<p>如果参数中包含非 <code>promise</code> 值,这些值将被忽略,但仍然会被放在返回数组中(如果 <code>promise</code> 完成的话):</p>
<pre class="brush: js">// this will be counted as if the iterable passed is empty, so it gets fulfilled
var p = Promise.all([1,2,3]);
// this will be counted as if the iterable passed contains only the resolved promise with value "444", so it gets fulfilled
var p2 = Promise.all([1,2,3, Promise.resolve(444)]);
// this will be counted as if the iterable passed contains only the rejected promise with value "555", so it gets rejected
var p3 = Promise.all([1,2,3, Promise.reject(555)]);
// using setTimeout we can execute code after the stack is empty
setTimeout(function(){
console.log(p);
console.log(p2);
console.log(p3);
});
// logs
// Promise { <state>: "fulfilled", <value>: Array[3] }
// Promise { <state>: "fulfilled", <value>: Array[4] }
// Promise { <state>: "rejected", <reason>: 555 }</pre>
<h3 id="Promise.all_的异步和同步"><code>Promise.all</code> 的异步和同步</h3>
<p>下面的例子中演示了 <code>Promise.all</code> 的异步性(如果传入的可迭代对象是空的,就是同步):</p>
<pre class="brush: js">// we are passing as argument an array of promises that are already resolved,
// to trigger Promise.all as soon as possible
var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
var p = Promise.all(resolvedPromisesArray);
// immediately logging the value of p
console.log(p);
// using setTimeout we can execute code after the stack is empty
setTimeout(function(){
console.log('the stack is now empty');
console.log(p);
});
// logs, in order:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: Array[2] }
</pre>
<p>如果 <code>Promise.all</code> 失败,也是一样的:</p>
<pre class="brush: js">var mixedPromisesArray = [Promise.resolve(33), Promise.reject(44)];
var p = Promise.all(mixedPromisesArray);
console.log(p);
setTimeout(function(){
console.log('the stack is now empty');
console.log(p);
});
// logs
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "rejected", <reason>: 44 }
</pre>
<p>但是,<code>Promise.all</code> <strong>当且仅当</strong>传入的可迭代对象为空时为同步:</p>
<pre class="brush: js">var p = Promise.all([]); // will be immediately resolved
var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
console.log(p);
console.log(p2)
setTimeout(function(){
console.log('the stack is now empty');
console.log(p2);
});
// logs
// Promise { <state>: "fulfilled", <value>: Array[0] }
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: Array[2] }
</pre>
<h3 id="Promise.all_的快速返回失败行为"><code>Promise.all</code> 的快速返回失败行为</h3>
<p><code>Promise.all</code> 在任意一个传入的 <code>promise</code> 失败时返回失败。例如,如果你传入的 <code>promise</code>中,有四个 <code>promise</code> 在一定的时间之后调用成功函数,有一个立即调用失败函数,那么 <code>Promise.all</code> 将立即变为失败。</p>
<pre class="brush: js">var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
//From console:
//"reject"
//You can also use .catch
Promise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}).catch(reason => {
console.log(reason)
});
//From console:
//"reject"
</pre>
<h2 id="技术规范">技术规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ES2015', '#sec-promise.all', 'Promise.all')}}</td>
<td>{{Spec2('ES2015')}}</td>
<td>Initial definition in an ECMA standard.</td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-promise.all', 'Promise.all')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{Compat("javascript.builtins.Promise.all")}}</p>
<h2 id="参见">参见</h2>
<ul>
<li>{{jsxref("Promise")}}</li>
<li>{{jsxref("Promise.race()")}}</li>
</ul>
|