哈喽,大家好,今天的文章由团队中的Uncle13提供。
Promise也算是前端面试中的高频面试题了,比如代码执行题、手撕代码题都少不了Promise。今天和大家分享一下Promise.all和Promise.allSettled的区别。
以下是正文:
Promise.all
和 Promise.allSettled
都是 JavaScript 中处理 Promise 对象的两个很有用的方法,但它们之间存在一些重要的区别。
Promise.all
Promise.all
方法接收一个 Promise 对象的数组作为参数,并返回一个新的 Promise 对象。这个新的 Promise 对象会在数组中的所有 Promise 对象都成功解决(resolve)后解决,并且它的解决值是一个包含所有解决值的数组。然而,如果数组中的任何一个 Promise 对象被拒绝(reject),那么 Promise.all
会立即以该拒绝原因被拒绝。
Promise.all
简单的例子:
let promise1 = Promise.resolve(3);
let promise2 = 42;
let promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
// expected output: Array [3, 42, "foo"]
});
Promise.allSettled
Promise.allSettled
的行为类似于 Promise.all
,但它不会因为数组中的某个 Promise 对象被拒绝而立即被拒绝。相反,它会等待数组中的所有 Promise 对象都解决或被拒绝,然后返回一个包含每个 Promise 对象状态的数组。每个状态对象都有一个 status
属性(值为 'fulfilled'
或 'rejected'
),以及一个 value
或 reason
属性(取决于 Promise 是解决还是被拒绝)。
Promise.allSettled
简单的例子:
let promise1 = Promise.resolve(3);
let promise2 = new Promise((resolve, reject) => reject('失败!'));
let promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.allSettled([promise1, promise2, promise3]).
then((results) => results.forEach((result) => console.log(result.status));
// expected output:
// "fulfilled"
// "rejected"
// "fulfilled"
假设我们有一个网页,需要从两个不同的 API 加载数据。我们希望在所有数据都加载完成后才更新页面。
Promise.all
function fetchDataFromApi1() {
return new Promise((resolve, reject) => {
// 模拟异步请求
setTimeout(() => {
resolve('数据来自 API 1');
}, 1000);
});
}
function fetchDataFromApi2() {
return new Promise((resolve, reject) => {
// 模拟另一个异步请求,可能会失败
setTimeout(() => {
reject('API 2 请求失败');
}, 500);
});
}
Promise.all([fetchDataFromApi1(), fetchDataFromApi2()])
.then(([data1, data2]) => {
// 假设这是更新页面的逻辑
console.log('页面更新:', data1, data2);
})
.catch((error) => {
// 如果任何一个 Promise 被拒绝,这里会捕获到错误
console.error('数据加载失败:', error);
});
// 输出: 数据加载失败: API 2 请求失败
由于 fetchDataFromApi2
失败了,Promise.all
会立即以 API 2 请求失败
为由被拒绝,因此不会执行 .then
中的页面更新逻辑。
Promise.allSettled
Promise.allSettled([fetchDataFromApi1(), fetchDataFromApi2()])
.then((results) => {
// 处理每个 Promise 的结果,无论成功或失败
const [result1, result2] = results;
if (result1.status === 'fulfilled') {
console.log('API 1 数据:', result1.value);
} else {
console.error('API 1 失败:', result1.reason);
}
if (result2.status === 'fulfilled') {
console.log('API 2 数据:', result2.value);
} else {
console.error('API 2 失败:', result2.reason);
}
// 尽管 API 2 失败,但我们仍然可以处理 API 1 的数据,或者执行其他逻辑
});
// 输出:
// API 1 数据: 数据来自 API 1
// API 2 失败: API 2 请求失败
使用 Promise.allSettled
,即使 fetchDataFromApi2
失败了,我们仍然可以处理 fetchDataFromApi1
成功返回的数据,并且不会中断整个流程。
假设我们有一个表单,每个字段都需要进行异步验证(例如,检查用户名是否已被注册)。我们想要在所有验证完成后才提交表单。
Promise.all
function validateUsername(username) {
return new Promise((resolve, reject) => {
// 模拟异步验证
setTimeout(() => {
if (username === 'existing') {
reject('用户名已被注册');
} else {
resolve('用户名可用');
}
}, 500);
});
}
function validateEmail(email) {
// 类似地,这里可以模拟另一个异步验证过程
}
const username = 'existing';
const email = 'user@example.com';
Promise.all([validateUsername(username), validateEmail(email)])
.then(([usernameValidation, emailValidation]) => {
// 如果所有验证都通过,则提交表单
console.log('表单可以提交:', usernameValidation, emailValidation);
})
.catch((error) => {
// 如果任何一个验证失败,则显示错误信息
console.error('验证失败:', error);
});
// 输出: 验证失败: 用户名已被注册
如果用户名验证失败,Promise.all
会立即被拒绝,不会执行表单提交逻辑。
Promise.allSettled
Promise.allSettled([validateUsername(username), validateEmail(email)])
.then((results) => {
// 处理每个验证的结果,无论成功或失败
const [usernameResult, emailResult] = results;
if (usernameResult.status === 'fulfilled') {
console.log('用户名验证成功:', usernameResult.value)
} else {
console.error('用户名验证失败:', usernameResult.reason);
}
if (emailResult.status === 'fulfilled') {
console.log('邮箱验证成功:', emailResult.value);
} else {
console.error('邮箱验证失败:', emailResult.reason);
}
// 我们可以根据验证结果决定下一步行动,比如显示错误提示或者仅提交部分通过验证的字段
// 即使用户名验证失败,我们仍然可以处理邮箱验证的结果
});
// 输出:
// 用户名验证失败: 用户名已被注册
// 邮箱验证成功: 邮箱可用
使用 Promise.allSettled
允许我们即使用户名验证失败,也仍然可以处理邮箱验证的结果。这样,我们可以为用户提供更详细的反馈,比如同时显示用户名和邮箱的验证状态,而不是在用户名验证失败时立即中断整个流程。
Promise.all
和 Promise.allSettled
都是用于处理 Promise 对象数组的方法,但它们的行为和用途有所不同。
Promise.all
等待数组中的所有 Promise 对象都成功解决(resolve)后,才返回一个新的、已解决的 Promise,其解决值是一个包含所有解决值的数组。如果数组中的任何一个 Promise 对象被拒绝(reject),则 Promise.all
会立即以该拒绝原因被拒绝。这种方法适用于需要所有 Promise 都成功的情况。
Promise.allSettled
则会等待数组中的所有 Promise 对象无论解决还是被拒绝都完成后,才返回一个新的、已解决的 Promise。其解决值是一个数组,数组中的每个元素都是一个对象,描述了对应 Promise 的最终状态(解决或被拒绝),以及相应的值或原因。即使某些 Promise 被拒绝,Promise.allSettled
也不会提前结束,而是会收集所有结果。这种方法适用于需要了解每个 Promise 的最终状态,无论其是否成功的情况。
简而言之,Promise.all
关注于所有 Promise 是否都成功,而 Promise.allSettled
则关注于所有 Promise 是否都已完成(无论成功或失败),并提供了每个 Promise 的最终结果。
最后
还没有使用过我们刷题网站(https://fe.ecool.fun/)或者刷题小程序的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。
老规矩,也给我们团队的辅导服务打个广告。