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
|
---
title: Promise.any()
slug: Web/JavaScript/Reference/Global_Objects/Promise/any
tags:
- Experimental
- JavaScript
- Method
- Promise
- Reference
translation_of: Web/JavaScript/Reference/Global_Objects/Promise/any
---
<p>{{JSRef}}</p>
<p><code>Promise.any()</code> 接收一个{{JSxRef("Promise")}}可迭代对象,只要其中的一个 <code>promise</code> 成功,就返回那个已经成功的 <code>promise</code> 。如果可迭代对象中没有一个 <code>promise</code> 成功(即所有的 <code>promises</code> 都失败/拒绝),就返回一个失败的 <code>promise </code>和{{JSxRef("Global_Objects/AggregateError", "AggregateError")}}类型的实例,它是 {{JSxRef("Error")}} 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和{{JSxRef("Promise.all()")}}是相反的。</p>
<div class="blockIndicator warning">
<p><strong>注意!</strong> <code>Promise.any()</code> 方法依然是实验性的,尚未被所有的浏览器完全支持。它当前处于 <a href="https://github.com/tc39/proposal-promise-any">TC39 第四阶段草案(Stage 4)</a></p>
</div>
<h2 id="语法">语法</h2>
<pre class="notranslate">Promise.any(<var>iterable</var>);</pre>
<h3 id="参数">参数</h3>
<dl>
<dt><code>iterable</code></dt>
<dd>一个<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol">可迭代</a>的对象, 例如 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a>。</dd>
</dl>
<h3 id="返回值">返回值</h3>
<ul>
<li>如果传入的参数是一个空的可迭代对象,则返回一个 <strong>已失败(already rejected)</strong> 状态的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>。</li>
<li>如果传入的参数不包含任何 <code>promise</code><var>,则返回</var>一个 <strong>异步完成</strong> (<strong>asynchronously resolved</strong>)的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>。</li>
<li>其他情况下都会返回一个<strong>处理中(pending)</strong> 的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>。 只要传入的迭代对象中的任何一个 <code>promise</code> 变成成功(resolve)状态,或者其中的所有的 <code>promises</code> 都失败,那么返回的 <code>promise</code> 就会 <strong>异步地</strong>(当调用栈为空时)<strong> </strong>变成成功/失败(resolved/reject)状态。</li>
</ul>
<h2 id="说明">说明</h2>
<p>这个方法用于返回第一个成功的 <code>promise</code> 。只要有一个 <code>promise</code> 成功此方法就会终止,它不会等待其他的 <code>promise</code> 全部完成。</p>
<p>不像 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all()</a> 会返回一组完成值那样(resolved values),我们只能得到一个成功值(假设至少有一个 <code>promise</code> 完成)。当我们只需要一个 <code>promise</code> 成功,而不关心是哪一个成功时此方法很有用的。</p>
<p>同时, 也不像 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/race">Promise.race()</a> 总是返回第一个结果值(resolved/reject)那样,这个方法返回的是第一个<em> 成功的</em> 值。这个方法将会忽略掉所有被拒绝的 <code>promise</code>,直到第一个 <code>promise</code> 成功。</p>
<h3 id="成功(Fulfillment):">成功(Fulfillment):</h3>
<p>当任何一个被传入的 <code>promise</code> 成功的时候, 无论其他的 <code>promises</code> 成功还是失败,此函数会将那个成功的 <code>promise</code> 作为返回值 。</p>
<ul>
<li>如果传入的参数是一个空的可迭代对象, 这个方法将会同步返回一个已经完成的 <code>promise</code>。</li>
<li>如果传入的任何一个 <code>promise</code> 已成功, 或者传入的参数不包括任何 <code>promise</code>, 那么 <code>Promise.any</code> 返回一个异步成功的 <code>promise</code>。</li>
</ul>
<h3 id="失败拒绝(Rejection):">失败/拒绝(Rejection):</h3>
<p>如果所有传入的 <code>promises</code> 都失败, <code>Promise.any</code> 将返回异步失败,和一个 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError">AggregateError</a> 对象,它继承自 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error">Error</a>,有一个 <code>error</code> 属性,属性值是由所有失败值填充的数组。</p>
<h2 id="示例">示例</h2>
<h3 id="First_to_fulfil">First to fulfil</h3>
<p>即使第一个返回的 promise 是失败的,<code>Promise.any()</code> 依然使用第一个成功状态的 promise 来返回。这与使用首个(无论 rejected 还是 fullfiled)promise 来返回的 {{jsxref("Promise.race()")}} 相反。</p>
<pre class="brush: js notranslate">const pErr = new Promise((resolve, reject) => {
reject("总是失败");
});
const pSlow = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "最终完成");
});
const pFast = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "很快完成");
});
Promise.any([pErr, pSlow, pFast]).then((value) => {
console.log(value);
// pFast fulfils first
})
// 期望输出: "很快完成"
</pre>
<h3 id="Rejections_with_AggregateError">Rejections with AggregateError</h3>
<p>如果没有 fulfilled (成功的) promise,<code>Promise.any()</code> 返回 {{jsxref("AggregateError")}} 错误。</p>
<pre class="brush: js notranslate">const pErr = new Promise((resolve, reject) => {
reject('总是失败');
});
Promise.any([pErr]).catch((err) => {
console.log(err);
})
// 期望输出: "AggregateError: No Promise in Promise.any was resolved"
</pre>
<h3 id="显示第一张已加载的图片">显示第一张已加载的图片</h3>
<p>在这个例子,我们有一个获取图片并返回 blob 的函数,我们使用 <code>Promise.any()</code> 来获取一些图片并显示第一张有效的图片(即最先 resolved 的那个 promise)。</p>
<pre class="brush: js notranslate">function fetchAndDecode(url) {
return fetch(url).then(response => {
if(!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
return response.blob();
}
})
}
let coffee = fetchAndDecode('coffee.jpg');
let tea = fetchAndDecode('tea.jpg');
Promise.any([coffee, tea]).then(value => {
let objectURL = URL.createObjectURL(value);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
})
.catch(e => {
console.log(e.message);
});</pre>
<h2 id="规范">规范</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">规范</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('Promise.any')}}</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{Compat("javascript.builtins.Promise.any")}}</p>
<h2 id="参见">参见</h2>
<ul>
<li>{{JSxRef("Promise")}}</li>
<li>{{JSxRef("Promise.all()")}}</li>
<li>{{JSxRef("Promise.race()")}}</li>
</ul>
|