Promise.allSettled用法全解析
本篇文章向大家介绍《JavaScript Promise.allSettled用法详解》,主要包括,具有一定的参考价值,需要的朋友可以参考一下。
Promise.allSettled用于等待所有Promise完成(无论成功或失败),并返回结果数组。它会收集每个Promise的status、value(fulfilled时)或reason(rejected时)。1. 它不会因某个Promise被拒绝而中断整体流程;2. 返回的结果数组中每个对象都包含对应Promise的最终状态和数据;3. 适用于需要获取所有异步任务执行结果(包括失败)的场景,如批量操作、多源数据聚合等;4. 可通过遍历、过滤、归类等方式处理结果,便于日志记录、错误统计和后续逻辑处理。
JavaScript中的Promise.allSettled
方法,是用来等待一组Promise都达到“已决”状态(fulfilled 或 rejected)后,才返回一个包含每个Promise结果状态的对象数组。这意味着无论每个Promise是成功还是失败,你都能得到它的最终信息,而不会因为其中一个Promise的失败而立即中断整个操作。它提供了一种更健壮的方式来处理并发的异步任务,尤其当你关心所有任务的独立结果时。

解决方案
Promise.allSettled
接收一个Promise可迭代对象(通常是数组),并返回一个新的Promise。这个新的Promise在所有输入的Promise都已决时解析,解析的值是一个数组,数组中的每个元素都描述了对应Promise的最终状态。
每个状态对象都有一个status
属性,值为'fulfilled'
或'rejected'
。
如果状态是'fulfilled'
,对象会有一个value
属性,包含Promise的成功值。
如果状态是'rejected'
,对象会有一个reason
属性,包含Promise的拒绝原因。

const promise1 = Promise.resolve(3); const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, '出错了!')); const promise3 = Promise.resolve(42); const promise4 = new Promise((resolve) => setTimeout(resolve, 50, 'Hello')); Promise.allSettled([promise1, promise2, promise3, promise4]) .then((results) => { console.log('所有Promise都已决:', results); // 示例输出: // [ // { status: 'fulfilled', value: 3 }, // { status: 'rejected', reason: '出错了!' }, // { status: 'fulfilled', value: 42 }, // { status: 'fulfilled', value: 'Hello' } // ] results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`Promise ${index + 1} 成功,值为: ${result.value}`); } else { console.error(`Promise ${index + 1} 失败,原因为: ${result.reason}`); } }); }) .catch((error) => { // Promise.allSettled的Promise本身不会被拒绝,除非传入的不是可迭代对象 console.error('发生了一个意料之外的错误:', error); });
这个方法特别适合那些你希望所有并发操作都能跑完,并且需要对每个操作的结果进行详细记录或展示的场景。我个人在使用它的时候,感觉就像是拿到了一份完整的“任务执行报告”,成功失败一目了然,非常省心。
Promise.allSettled与Promise.all、Promise.race有何不同?
理解Promise.allSettled
的独特之处,需要把它和另外两个常用的Promise组合方法——Promise.all
和Promise.race
——放在一起比较。它们各自有不同的应用场景和行为模式,选错一个,可能整个异步流程就跑偏了。

Promise.all
是最严格的。它接收一组Promise,并且只有当所有Promise都成功(fulfilled)时,它返回的Promise才会成功,并返回一个包含所有成功值的数组。但如果这组Promise中,哪怕只有一个Promise失败(rejected)了,Promise.all
就会立即拒绝,并返回第一个拒绝的原因。它是一个“全有或全无”的策略,适用于所有任务都必须成功才能继续的场景,比如多个数据都加载成功才渲染页面。我经常用它来确保一个组件所需的所有数据都到位了,才开始渲染,任何一个数据缺失都会导致渲染失败。
Promise.race
则截然不同。它也接收一组Promise,但它只关心“最快”的那个。只要这组Promise中有一个Promise率先达到已决状态(无论是成功还是失败),Promise.race
返回的Promise就会立即以那个Promise的结果(成功值或失败原因)来解析或拒绝。它就像一场赛跑,谁先到终点,谁就决定了最终结果。这在比如设置超时机制时非常有用,你可以让一个请求Promise和一个定时器Promise一起赛跑,如果定时器先完成(超时),就拒绝请求。
而Promise.allSettled
,它不追求“全成功”,也不追求“最快”,它追求的是“全知”。它会等待所有传入的Promise都尘埃落定(settled),无论是成功还是失败,它都会收集每个Promise的最终状态和结果(或原因),然后返回一个包含这些详细信息的数组。这个数组里的每个对象都明确告诉你,对应的Promise是成功了,成功值是什么;还是失败了,失败原因是什么。我发现,在需要确保所有操作都尝试执行,并且我关心每个操作的最终状态时,allSettled
简直是救星。不像all
那样,一个失败就全盘皆输,allSettled
给我提供了一个完整的“战报”,让我能基于这份报告做后续的错误处理、日志记录或者部分成功展示。
在实际项目中,何时优先考虑使用Promise.allSettled?
在我的实际开发经验中,Promise.allSettled
的出场频率,虽然不如Promise.all
那么高,但在特定场景下,它几乎是不可替代的。我通常会在以下几种情况中优先考虑使用它:
一个很典型的例子是批量操作。想象一下,你需要向服务器发送一批用户通知,或者批量更新一组用户数据。这里面可能有些用户ID是无效的,或者某些更新操作因为权限问题会失败。如果用Promise.all
,一旦有一个通知发送失败,整个批处理就会中断,你可能就无法得知其他通知是否成功发送了。而使用Promise.allSettled
,你可以确保所有的通知发送尝试都会完成,然后你就能得到一份详尽的报告:哪些通知成功了,哪些失败了,失败的原因是什么。这对于后续的重试、错误日志记录或者给用户反馈“部分成功”的消息至关重要。
另一个场景是多源数据聚合与展示。比如,你的前端页面需要从多个独立的API接口获取数据来填充不同的模块。这些API可能由不同的团队维护,或者它们的稳定性不一。你希望即使某个API调用失败了,页面上的其他模块也能正常显示数据,而不是整个页面都崩溃或者显示一个空白。用Promise.allSettled
,你可以并行发起所有请求,然后根据每个请求的结果,决定是渲染对应模块的数据,还是显示一个友好的错误提示。这样用户体验会好很多,不会因为一个接口的小问题就影响到整个页面的可用性。
我常常在做一些后台任务调度时用到它。比如,我要给一批用户发送通知,有些用户可能已注销,有些邮箱无效,我不可能因为一个失败就停止整个批处理。allSettled
让我能优雅地处理这些边缘情况,并生成一份详细的执行报告。我甚至会用它来做一些前端的“健康检查”,同时请求多个关键资源,然后根据allSettled
的结果来判断哪些资源加载失败了,并进行相应的处理。它提供的那种“即使有失败,我也要知道所有情况”的哲学,在很多业务场景下都显得非常实用。
如何优雅地处理Promise.allSettled返回的结果?
处理Promise.allSettled
返回的结果,其实就是一次数据清洗和分类的过程。由于它返回的是一个包含状态和值的数组,我们需要遍历这个数组,根据每个元素的status
属性来区分成功和失败,并提取相应的数据。
最直接的方式是使用forEach
或for...of
循环遍历结果数组:
async function processAllTasks() { const tasks = [ Promise.resolve('数据A加载成功'), Promise.reject(new Error('数据B加载失败:网络错误')), new Promise(res => setTimeout(() => res('数据C准备就绪'), 200)), Promise.reject('数据D加载失败:权限不足') ]; const results = await Promise.allSettled(tasks); console.log('--- 任务处理报告 ---'); results.forEach((item, index) => { if (item.status === 'fulfilled') { console.log(`任务 ${index + 1} (成功): ${item.value}`); // 可以在这里更新UI、存储成功数据等 } else { console.error(`任务 ${index + 1} (失败): ${item.reason}`); // 可以在这里记录日志、显示错误消息、触发重试等 } }); // 统计成功和失败的数量 const fulfilledCount = results.filter(item => item.status === 'fulfilled').length; const rejectedCount = results.filter(item => item.status === 'rejected').length; console.log(`\n总任务数: ${results.length}, 成功: ${fulfilledCount}, 失败: ${rejectedCount}`); } processAllTasks();
这种遍历方式非常直观,能让你对每个任务的最终状态进行细致的处理。
更进一步,如果你想把成功和失败的结果分别归类,或者进行更复杂的数据转换,可以使用数组的map
或reduce
方法。比如,我有时候会把成功的结果提取出来放到一个数组,失败的结果及其原因放到另一个数组,方便后续统一处理:
async function categorizeResults() { const requests = [ fetch('https://api.example.com/data1').then(res => res.json()), // 假设成功 fetch('https://api.example.com/data2').then(res => res.json()), // 假设失败 fetch('https://api.example.com/data3').then(res => res.json()) // 假设成功 ]; const allOutcomes = await Promise.allSettled(requests); const successfulData = allOutcomes .filter(outcome => outcome.status === 'fulfilled') .map(outcome => outcome.value); const failedReasons = allOutcomes .filter(outcome => outcome.status === 'rejected') .map(outcome => outcome.reason); console.log('\n--- 分类处理后的结果 ---'); console.log('成功获取的数据:', successfulData); console.log('失败的原因:', failedReasons); // 甚至可以进一步处理失败原因,比如统计错误类型 const errorMap = failedReasons.reduce((acc, reason) => { const errorMessage = reason instanceof Error ? reason.message : String(reason); acc[errorMessage] = (acc[errorMessage] || 0) + 1; return acc; }, {}); console.log('错误类型统计:', errorMap); } // 模拟fetch请求,以展示allSettled的实际效果 // 在实际运行中,需要替换为真实的API请求或模拟Promise行为 function fetch(url) { return new Promise((resolve, reject) => { if (url.includes('data2')) { setTimeout(() => reject(new Error(`Failed to fetch ${url}`)), 50); } else { setTimeout(() => resolve({ json: () => Promise.resolve({ source: url, content: 'some data' }) }), 50); } }); } categorizeResults();
处理allSettled
的结果,关键在于它的结构化输出。这给了我们极大的灵活性去定制后续的逻辑,无论是仅仅打印日志、更新UI,还是触发更复杂的业务流程,都能做到既全面又精准。我通常会把成功和失败的分别归类,有时候还会用reduce
来统计成功的数量和失败的原因分布,这样一眼就能看出整体情况。这比单纯地打印出来要有用得多,尤其是在调试或者做数据分析的时候。
今天关于《Promise.allSettled用法全解析》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

- 上一篇
- Golang锁竞争优化:sync.Pool与原子操作实战

- 下一篇
- PHPMyAdmin账户锁定怎么解锁
-
- 文章 · 前端 | 48秒前 |
- HTML5CustomEvent教程及触发方法
- 213浏览 收藏
-
- 文章 · 前端 | 6分钟前 |
- CSSflex-grow打造数据对比柱状图教程
- 425浏览 收藏
-
- 文章 · 前端 | 7分钟前 |
- CSS制作指针式数据仪表盘教程
- 200浏览 收藏
-
- 文章 · 前端 | 12分钟前 |
- CSS下拉筛选动画实现技巧
- 255浏览 收藏
-
- 文章 · 前端 | 13分钟前 | 异步队列 状态管理 Promise 链式调用 PromiseQueue
- Promise异步队列实现全解析
- 323浏览 收藏
-
- 文章 · 前端 | 14分钟前 |
- BOM页面OCR识别怎么实现?
- 433浏览 收藏
-
- 文章 · 前端 | 19分钟前 |
- HTML表格数据压缩传输的实现方法有哪些?
- 245浏览 收藏
-
- 文章 · 前端 | 25分钟前 |
- CSSonly-child选择器使用教程
- 379浏览 收藏
-
- 文章 · 前端 | 36分钟前 |
- 自定义HTML视频播放器样式技巧
- 110浏览 收藏
-
- 文章 · 前端 | 39分钟前 |
- HTML文本下划线设置方法大全
- 180浏览 收藏
-
- 文章 · 前端 | 54分钟前 |
- 理解JavaScriptawait:异步错误处理技巧
- 272浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 边界AI平台
- 探索AI边界平台,领先的智能AI对话、写作与画图生成工具。高效便捷,满足多样化需求。立即体验!
- 418次使用
-
- 免费AI认证证书
- 科大讯飞AI大学堂推出免费大模型工程师认证,助力您掌握AI技能,提升职场竞争力。体系化学习,实战项目,权威认证,助您成为企业级大模型应用人才。
- 424次使用
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 561次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 662次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 570次使用
-
- 优化用户界面体验的秘密武器:CSS开发项目经验大揭秘
- 2023-11-03 501浏览
-
- 使用微信小程序实现图片轮播特效
- 2023-11-21 501浏览
-
- 解析sessionStorage的存储能力与限制
- 2024-01-11 501浏览
-
- 探索冒泡活动对于团队合作的推动力
- 2024-01-13 501浏览
-
- UI设计中为何选择绝对定位的智慧之道
- 2024-02-03 501浏览