作者:@Angela Caldas
原文:https://dev.to/sucodelarangela/explorando-promises-all-vs-allsettled-race-vs-any-kk9
背景
在 2015 年,随着 ECMAScript 6(ES2015)的发布,JavaScript 引入了 Promise 来简化异步操作的处理。Promise 的出现极大地改善了开发者处理异步任务的体验。随着 JavaScript 版本的不断更新,Promise 也增加了新的方法,如 Promise.allSettled()
和 Promise.any()
,这些方法进一步增强了 Promise 的功能。
【第3360期】在JavaScript中从外部解决Promise:实际应用场景
要点
本文主要探讨了 Promise.all
、Promise.allSettled
、Promise.race
和 Promise.any
这四个方法的区别及其适用场景。
核心概念回顾
Promises:Promises 是处理异步操作的一种模式,代表一个异步操作最终完成或失败的结果。它有三种状态:pending(进行中)、fulfilled(已完成)和 rejected(已拒绝)。
异步操作:指不阻塞主线程,允许程序在等待操作完成的同时继续执行其他任务的操作,例如网络请求、定时器等。
并行执行:指同时执行多个任务,例如同时发起多个网络请求。
错误处理:指捕获和处理异步操作中可能发生的错误。
成功回调:当 Promise 成功完成时执行的函数。
失败回调:当 Promise 失败时执行的函数。
分析
Promise.all
vs Promise.allSettled
:聚焦结果
Promise.all
接收一个 Promise 数组作为参数。
并行执行所有 Promise。
当所有 Promise 都成功解决时,
Promise.all
才会成功解决,并返回所有结果。如果任何一个 Promise 失败,
Promise.all
会立即拒绝,并返回失败的原因,后续的 Promise 将不再执行。
使用 Promise.all
同时获取用户和产品数据。只有当两个 fetch 请求都成功时,才会返回数据。如果任何一个请求失败,Promise.all
就会立即拒绝,并返回失败的原因,后续的 fetch 请求将不再执行。
async function buscarDadosParalelo () {
const [ usuarios, produtos ] = await Promise.all([
fetch('/api/usuarios').then(resp => resp.json()),
fetch('/api/produtos').then(resp => resp.json()),
]);
return { usuarios, produtos };
}
适用场景:当需要确保所有异步操作都成功完成时,Promise.all
是一个很好的选择。例如,在需要同时获取多个 API 数据并确保所有数据都成功返回时。
Promise.allSettled
同样接收一个 Promise 数组作为参数。
并行执行所有 Promise。
无论 Promise 是成功还是失败,
Promise.allSettled
都会返回一个包含每个 Promise 状态的对象数组。不会因为某个 Promise 失败而中断,所有 Promise 都会执行完毕。
展示了使用 Promise.allSettled
同时获取用户和产品数据。无论请求成功还是失败,Promise.allSettled
都会返回一个包含每个 Promise 状态的对象数组。每个对象包含 status 属性(值为 "fulfilled" 或 "rejected")和 value 或 reason 属性。
async function buscarDadosParaleloComFalhas () {
const resultados = await Promise.allSettled([
fetch('/api/usuarios').then(resp => resp.json()),
fetch('/api/produtos').then(resp => resp.json()),
]);
// 检查每个结果:
const dados = resultados.map(resultado => {
if (resultado.status === 'fulfilled') {
return resultado.value;
} else {
console.error(resultado.reason);
return null;
}
});
return dados;
}
适用场景:当需要知道所有异步操作的最终状态,而不希望某个操作的失败影响其他操作时,Promise.allSettled
是一个更好的选择。例如,在需要记录多个 API 调用的状态时。
Promise.race
vs Promise.any
:聚焦速度
Promise.race
接收一个 Promise 数组作为参数。
并行执行所有 Promise。
返回第一个完成的 Promise 的结果,无论是成功还是失败。
使用 Promise.race 获取用户信息。它使用 Promise.race
从缓存、本地数据库和 API 中获取数据,并设置一个 5 秒的超时。 Promise.race
将返回第一个完成的 Promise 的结果,无论是成功还是失败。
async function buscarDadosUsuario () {
const timeout = new Promise((_, reject) => {
setTimeout(() => reject('Timeout!'), 5000);
});
try {
// 使用 race 获取第一个可用的结果
const resultado = await Promise.race([
buscarCache,
buscarBancoLocal,
buscarAPI,
timeout
]);
return resultado;
} catch (erro) {
console.log(erro);
// 如果出现错误,则在此处停止执行
}
}
适用场景:当需要尽快获取一个结果,而不关心结果是成功还是失败时,Promise.race
是一个合适的选择。例如,在需要设置超时机制时,可以使用 Promise.race
来确保请求在一定时间内完成。
Promise.any
同样接收一个 Promise 数组作为参数。
并行执行所有 Promise。
返回第一个成功解决的 Promise 的结果,忽略所有失败的 Promise。
只有在所有 Promise 都失败时,
Promise.any
才会拒绝。
使用 Promise.any
从多个来源获取用户信息。它将尝试从缓存、本地数据库和 API 中获取数据,并返回第一个成功完成的 Promise 的结果。只有当所有 Promise 都失败时,Promise.any
才会拒绝。
async function buscarDadosUsuario () {
try {
// 返回第一个成功响应的搜索结果
const resultado = await Promise.any([
buscarCache,
buscarBancoLocal,
buscarAPI
]);
return resultado;
} catch (erro) {
console.log(erro);
// 仅当所有搜索都失败时才会执行此操作
}
}
适用场景:当需要确保至少有一个异步操作成功时,Promise.any
是一个理想的选择。例如,在需要从多个数据源获取数据,并选择最快返回成功的数据源时。
选择合适的 Promise 方法取决于应用场景的具体需求。
如果需要所有操作都成功,选择 Promise.all。
如果需要所有结果无论成功或失败,选择 Promise.allSettled。
如果需要最快的结果,选择 Promise.race。
如果只需要至少一个成功结果,选择 Promise.any。
影响
这些新的 Promise 方法为开发者提供了更多的灵活性和控制力,使得处理复杂的异步操作变得更加简单和高效。随着 JavaScript 生态系统的不断发展,这些方法的使用将变得更加普遍,特别是在需要处理大量并发请求的现代 Web 应用中。
结论
Promise.all
、Promise.allSettled
、Promise.race
和 Promise.any
各自有其独特的应用场景,开发者应根据具体需求选择合适的方法。随着异步编程在现代应用中的重要性不断提升,掌握这些方法的使用将成为开发者的一项重要技能。未来,随着 JavaScript 标准的进一步演进,我们可能会看到更多增强异步编程体验的新特性。
AI 阅:了解技术资讯的一种方式。
🚀可直接通过阅读原文了解详细内容。