在 ES9 版本中,Promise 实例新增了两个静态方法 Promise.allSettled() 和 Promise.any()。这两个方法在处理异步任务时有着很大的帮助作用,本篇文章将对它们做详细介绍,并提供示例代码。
Promise.allSettled()
Promise.allSettled() 方法接收一个 Promise 实例数组作为参数,返回一个新的 Promise 实例。当且仅当所有的 Promise 实例都已经跑完(无论是 fulfilled 还是 rejected),返回的新的 Promise 实例就会 fulfilled 。如果有任意一个 Promise 实例 rejected,新的 Promise 实例就会 rejected。
假设我们需要同时加载两个图片资源,并在它们都加载完成后将它们展示出来。如果其中一个图片资源加载失败,我们希望仍然展示另一个正常加载的图片,可以使用 Promise.allSettled() 实现。
// www.javascriptcn.com code example
const img1 = loadImage('https://example.com/1.jpg');
const img2 = loadImage('https://example.com/2.jpg');
Promise.allSettled([img1, img2]).then(results => {
const fulfilledImgs = results.filter(result => result.status === 'fulfilled');
if (fulfilledImgs.length > 0) {
const firstImg = fulfilledImgs[0].value;
document.body.appendChild(firstImg);
} else {
console.error('Both images failed to load');
}
});当然,我们也可以通过给定的例子来展示其效果:
// www.javascriptcn.com code example
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('fulfilled'), 3000)
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject('rejected'), 2000)
});
Promise.allSettled([promise1, promise2])
.then(results => {
console.log(results);
})
.catch(error => {
console.error(error);
})在上述代码中,我们模拟了两个Promise实例,并将它们存放在一个数组中传入 Promise.allSettled() 方法中。实际运行结果如下:
[
{ status: 'fulfilled', value: 'fulfilled' },
{ status: 'rejected', reason: 'rejected' }
]本例中,我们在promise1的resolve函数里等待了3秒钟,promise2的reject函数则在2秒后直接返回了一个rejected状态。到最后,Promise.allSettled() 方法会返回一个 Promise 实例,并将promise1的fulfilled状态和promise2的rejected状态都解析为对象。这些对象都包含status键,其值分别为'fulfilled'和'rejected'。如果 Promise 实例是 fulfilled 的,还会包含一个value键,其值为返回的值。如果是 rejected 的,则还有一个reason键,其值为 reject 原因。
Promise.any()
ES9 Promise 对象的另一个新方法是 Promise.any()。该方法也接收一个 Promise 实例数组作为参数,并返回一个 Promise 实例,该 Promise 实例会在数组中的任何一个 Promise 实例 fulfilled 后立即变成 fulfilled 状态,如果所有的 Promise 实例都 rejected,那么新的 Promise 实例就会 rejected。
假设我们需要先尝试从第一个网站获取资源,如果失败再到第二个网站获取同样的资源。当然,只要在其中一个网站成功获取到资源,我们就可以立即使用它。这时,我们可以使用 Promise.any() 方法实现:
// www.javascriptcn.com code example
const getResource = url => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
if (this.status === 200) {
resolve(JSON.parse(this.responseText));
} else {
reject(new Error(`Could not fetch ${url}`));
}
};
xhr.onerror = function() {
reject(new Error(`Could not fetch ${url}`));
};
xhr.send();
});
};
const resources = [
getResource('https://example1.com/hello'),
getResource('https://example2.com/hello')
];
Promise.any(resources).then(result => {
console.log(result);
}).catch(error => {
console.error(error);
});同样的,我们提供了一个例子来展示其效果:
// www.javascriptcn.com code example
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('fulfilled'), 3000)
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject('rejected'), 2000)
});
Promise.any([promise1, promise2])
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
})在本例中,promise1 的 resolve 函数等待了 3 秒钟,而 promise2 的 reject 函数在 2 秒钟后直接返回一个 rejected 状态。最后,由于 promise1 被 fulfilled 了,所以新的 Promise 实例立即变成 fulfilled 状态。
小结
通过 ES9 引入的 Promise.allSettled() 方法和 Promise.any() 方法,我们可以更方便地处理异步任务。本文介绍了这两个方法的用法和示例代码,希望对你的技术学习和实践有所帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d7cddba941bf7134df7e0c