Promise API
Promise.resolve
let promise = Promise.resolve(value);
// same
let promise = new Promise(resolve => resolve(value));
// example
function loadCached(url) {
let cache = loadCached.cache || (loadCached.cache = new Map());
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;
});
}
Promise.reject
let promise = Promise.reject(error);
// same
let promise = new Promise((resolve, reject) => reject(error));
Promise.all
let promise = Promise.all([...promises...]);
Promise.all([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
new Promise((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
new Promise((resolve, reject) => setTimeout(() => resolve(3), 1000)) // 3
]).then(alert); // 1,2,3 when promises are ready: each promise contributes an array member
// example
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://api.github.com/users/jeresig'
];
// map every url to the promise fetch(github url)
let requests = urls.map(url => fetch(url));
// Promise.all waits until all jobs are resolved
Promise.all(requests)
.then(responses => responses.forEach(
response => alert(`${response.url}: ${response.status}`)
));
// example
let names = ['iliakan', 'remy', 'jeresig'];
let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));
Promise.all(requests)
.then(responses => {
// all responses are ready, we can show HTTP status codes
for(let response of responses) {
alert(`${response.url}: ${response.status}`); // shows 200 for every url
}
return responses;
})
// map array of responses into array of response.json() to read their content
.then(responses => Promise.all(responses.map(r => r.json())))
// all JSON answers are parsed: "users" is the array of them
.then(users => users.forEach(user => alert(user.name)));
// 如果任何 promise 为 rejected,Promise.all 就会立即以 error reject,
// 其他 promise 会继续执行,并最终为 settle,但它们的结果会被忽略
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!
// iterable 中的任何一个不是 promise,它就会被封装进 Promise.resolve
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000)
}),
2, // treated as Promise.resolve(2)
3 // treated as Promise.resolve(3)
]).then(alert); // 1, 2, 3
Promise.allSettled
// 任何 promise 为 rejected,Promise.all 就会立即以 error reject
//
Promise.all([
fetch('/template.html'),
fetch('/style.css'),
fetch('/data.json')
]).then(render); // render method needs them all
// Promise.allSettled 會等到所有 promise 結束,即使有錯誤產生
// {status:"fulfilled", value:result} for successful responses,
// {status:"rejected", reason:error} for errors.
// example
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)))
.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}`);
}
});
});
// results in the line (*)
[
{status: 'fulfilled', value: ...response...},
{status: 'fulfilled', value: ...response...},
{status: 'rejected', reason: ...error object...}
]
// polyfill
if(!Promise.allSettled) {
Promise.allSettled = function(promises) {
return Promise.all(promises.map(p => Promise.resolve(p).then(v => ({
state: 'fulfilled',
value: v,
}), r => ({
state: 'rejected',
reason: r,
}))));
};
}
Promise.race
// 与 Promise.all 类似,所有的 promise 都是可迭代的,但不会等待所有都完成
// 只等待第一个完成(或者有 error),然后继续执行。
let promise = Promise.race(iterable);
// example
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
Last updated