作者:@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.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.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.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.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 阅:了解技术资讯的一种方式。
🚀可直接通过阅读原文了解详细内容。