Promise.all
接受一个 promise
数组作为参数,并返回一个新的 promise
promise
都被 settled
时,新的 promise
才会 resolve
,并且其结果数组将成为新的 promise
的结果。promise
中的顺序相同。即使第一个 promise
花费了最长的时间才 resolve
,但它仍是结果数组中的第一个。let promise = Promise.all([...promises...]);
//下面的Promise.all在3秒之后被settled,然后它的结果就是一个[1, 2, 3]数组
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then(alert); // 1,2,3 当上面这些 promise 准备好时:每个 promise 都贡献了数组中的一个元素
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://api.github.com/users/jeresig'
];
// 将每个 url 映射(map)到 fetch 的 promise 中
/*
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
*/
let requests = urls.map(url => fetch(url));
// Promise.all 等待所有任务都 resolved
Promise.all(requests)
.then(responses => responses.forEach(
response => alert(`${response.url}: ${response.status}`)
));
let names = ['iliakan', 'remy', 'jeresig'];
let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));
Promise.all(requests)
.then(responses => {
// 所有响应都被成功 resolved
for(let response of responses) {
alert(`${response.url}: ${response.status}`); // 对应每个 url 都显示 200
}
return responses;
})
// 将响应数组映射(map)到 response.json() 数组中以读取它们的内容
.then(responses => Promise.all(responses.map(r => r.json())))
// 所有 JSON 结果都被解析:"users" 是它们的数组
.then(users => users.forEach(user => alert(user.name)));
Promise.all([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).catch(alert); // Error: Whoops!
Promise.all(iterable)
允许在 iterable
中使用 non-promise
的“常规”值Promise.all(...)
接受可迭代对象(iterable
)的 promise
(大多数情况下是数组)。但是,如果这些对象中的任意一个都不是 promise
,那么它将被“按原样”传递给结果数组。Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000)
}),
2,
3
]).then(alert); // 1, 2, 3
Promise.allSettled
等待所有的 promise
都被 settle
,无论结果如何。结果数组具有:{status:"fulfilled", value:result}
对于成功的响应,{status:"rejected", reason:error}
对于 error。let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://no-such-url'
];
Promise.allSettled(urls.map(url => fetch(url)))
/**
results内容:
*[
{status: 'fulfilled', value: ...response...},
{status: 'fulfilled', value: ...response...},
{status: 'rejected', reason: ...error object...}
]
*/
.then(results => { // (*)
results.forEach((result, num) => {
if (result.status == "fulfilled") {
alert(`${urls[num]}: ${result.value.status}`);
}
if (result.status == "rejected") {
alert(`${urls[num]}: ${result.reason}`);
}
});
});
Promise.allSettled
,很容易进行 polyfill
:if (!Promise.allSettled) {
const rejectHandler = reason => ({ status: 'rejected', reason });
const resolveHandler = value => ({ status: 'fulfilled', value });
Promise.allSettled = function (promises) {
const convertedPromises = promises.map(p => Promise.resolve(p).then(resolveHandler, rejectHandler));
return Promise.all(convertedPromises);
};
}
promises.map
获取输入值,并通过 p => Promise.resolve(p)
将输入值转换为 promise
,然后向每一个 promise
都添加 .then
处理程序(handler
)handler
)将成功的结果 value
转换为 {status:'fulfilled', value
},将 error
reason
转换为 {status:'rejected', reason
}。这正是 Promise.allSettled
的格式。let promise = Promise.race(iterable);
Promise.race([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert); // 1
let promise = new Promise(resolve => resolve(value));
let cache = new Map();
function loadCached(url) {
if (cache.has(url)) {
return Promise.resolve(cache.get(url)); // (*)
}
return fetch(url)
.then(response => response.text())
.then(text => {
cache.set(url,text);
return text;
});
}
let promise = new Promise((resolve, reject) => reject(error));