如果你偶然发现了这篇文章,你可能已经对 promises 很熟悉了。但对于那些新接触 JavaScript 的人来说,我们来详细解释一下。从本质上讲,Promise 对象表示异步操作的最终完成或失败。有趣的是,当 promise
被创建时,其值可能不会立即可用。
const promise = new Promise((resolve, reject) => {
// 一些异步操作
if (/* 操作成功 */) {
resolve(result);
} else {
reject(error);
}
});
它们有3种状态:
一旦 promise 被解决,你可以使用 .then()
来处理结果,使用 .catch()
来管理其执行过程中出现的任何错误。
promise
.then(result => {
console.log('成功:', result);
})
.catch(error => {
console.error('错误:', error);
});
当同时处理多个 promises
时,你可以利用内置的 Promise.all([])
方法。此方法接受一个 promises 数组并返回一个统一的 promise。关键是,只有当所有输入的 promises
都成功解决时,这个组合的 promise
才会解决。如果其中一个失败,整个 promise
就会被拒绝。以下是一个例子:
const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');
const promise3 = fetch('https://api.example.com/data3');
Promise.all([promise1, promise2, promise3])
.then(values => {
console.log('所有数据已获取:', values);
})
.catch(error => {
console.error('发生错误:', error);
});
这种方法通常用于多个相关异步任务且其工作相互依赖的情况,因此我们希望在继续执行代码之前,所有异步任务都能成功。
使用 Promise.allSettled([])
与 Promise.all([])
类似,但不同之处在于它会等待所有输入的 promises
完成或被拒绝,并返回描述每个 promise
结果的对象数组。
const promise1 = Promise.resolve('成功 1');
const promise2 = Promise.reject('错误 2');
const promise3 = Promise.resolve('成功 3');
Promise.allSettled([promise1, promise2, promise3])
.then(results => {
results.forEach(result => {
if(result.status === 'fulfilled') {
console.log('成功取得值:', result.value);
} else {
console.error('因为原因被拒绝:', result.reason);
}
});
});
//输出
// 成功取得值:成功 1
// 因为原因被拒绝:错误 2
// 成功取得值:成功 3
它通常用于处理不互相依赖的异步操作,你想知道每一个的结果。
总的来说,使用 Promise.allSettled()
而不是 Promise.all()
在大多数常见情况下都有其优势:
如果 promises 中的任何一个被拒绝,Promise.all()
的立即拒绝可能会使得确定其他 promises
的状态变得困难,尤其是当其他 promises
成功解决时。使用 Promise.allSettled([])
可以为你提供结果的完整画面。
Promise.all()
的“快速失败”方法在你想继续进行,而其中一个失败时可能会受到限制,而 Promise.allSettled()
允许你单独处理每个 promise
的结果。
当处理批量操作时,其中的单个操作是独立的,你可能不希望整个批次因操作失败而失败。
使用 Promise.allSettled()
后,你可以在获得所有 promises 的结果后做出更明智的决策。例如,当你从不同的 API 获取数据,其中一个失败时,你可以决定是否继续处理数据或提供带有错误消息的通知。
通常,为用户提供必要的部分结果和错误通知要比使用某些通用消息使整个操作失败更好。Promise.allSettled() 使这种方法易于实施。
总之,Promise.all() 在某些情况下可能很有价值,但 Promise.allSettled() 为大多数场景提供了更灵活和更有韧性的方法。