当前位置: 首页 > article >正文

Vue3并发请求Promise.allSettled的结果处理优化示例

原来的代码// 发送网络请求获取数据 const fetchData async (id: number, workflowInstanceId: number, activityId: number) { const currentId requestId; loading.value true; try { // 并发请求 const [detailResult, fieldResult, auditResult] await Promise.allSettled([ // 获取资金分配明细列表 capitalAllocateApi.getAllocateDetail(id), // 获取活动可编辑字段 getActivityEditableFieldList(activityId), // 获取审批信息列表 getAuditInfoList(workflowInstanceId) ]); // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; // 更新数据 if (detailResult.status fulfilled detailResult.value?.data) { allocateDatas.value detailResult.value.data; } // 等待 watch 回调执行此时 dataLoaded 仍为 false不会错误修改 isModified await nextTick(); dataLoaded.value true; // 标记数据加载完成 isModified.value false; // 重置修改状态未修改 if (fieldResult.status fulfilled fieldResult.value?.data) { editableFieldDatas.value fieldResult.value.data; } if (auditResult.status fulfilled auditResult.value?.data) { auditDatas.value auditResult.value.data; } // 处理错误并友好提示 const hasDetailError detailResult.status ! fulfilled || !detailResult.value?.data; const hasFieldError fieldResult.status ! fulfilled || !fieldResult.value?.data; const hasAuditError auditResult.status ! fulfilled || !auditResult.value?.data; if (hasDetailError hasAuditError) { ElMessage.error(数据加载失败请稍后重试); } else { if (hasDetailError) ElMessage.error(资金分配明细加载失败); if (hasFieldError) ElMessage.error(可编辑字段加载失败); if (hasAuditError) ElMessage.error(审核信息加载失败); } // 渐进式加载核心数据先展示次要数据后加载获取办理选项 const activityInstance props.capitalAllocate?.activityInstance; if (activityInstance) { // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; getAuditOption(activityInstance) .then((result) { // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; auditOption.value result.data; }) .catch((error) { // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; console.error(获取办理选项失败:, error); }); } } catch (error) { console.error(请求过程发生意外错误, error); ElMessage.error(系统错误请稍后重试); } finally { if (isMounted currentId requestId) loading.value false; } };错误处理代码冗余fetchData 中逐个判断并提示可读性较差。 代码臃肿维护成本高。 可封装一个统一处理函数或使用 try-catch 结合错误状态码区分。 这里应该如何修改针对fetchData中错误处理代码冗余的问题可以通过封装统一处理函数或结构化请求配置来优化。以下是两种可行的改进方案重点保持原有业务逻辑核心数据明细审批都失败时显示整体失败其他情况分别提示。方案一封装通用处理函数将请求结果的处理逻辑抽象为一个函数接收请求结果、对应的数据 ref、错误消息和是否为“核心数据”标识。通过遍历请求配置数组统一处理。代码示例typescriptconst fetchData async (id: number, workflowInstanceId: number, activityId: number) { const currentId requestId; loading.value true; try { // 定义请求配置列表 const requests [ { promise: capitalAllocateApi.getAllocateDetail(id), ref: allocateDatas, errorMsg: 资金分配明细加载失败, isCore: true, // 核心数据 }, { promise: getActivityEditableFieldList(activityId), ref: editableFieldDatas, errorMsg: 可编辑字段加载失败, isCore: false, }, { promise: getAuditInfoList(workflowInstanceId), ref: auditDatas, errorMsg: 审核信息加载失败, isCore: true, }, ]; // 并发执行所有请求 const results await Promise.allSettled(requests.map(r r.promise)); // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; // 统计核心数据成功/失败数量 let coreSuccessCount 0; let coreFailCount 0; const errors: string[] []; // 遍历结果依次处理 results.forEach((result, index) { const config requests[index]; if (result.status fulfilled result.value?.data) { // 成功且有数据 config.ref.value result.value.data; if (config.isCore) coreSuccessCount; } else { // 失败或无数据 if (config.isCore) coreFailCount; errors.push(config.errorMsg); } }); // 等待可能的 watch 回调执行 await nextTick(); dataLoaded.value true; isModified.value false; // 核心数据全部失败提示整体错误否则分别提示 if (coreSuccessCount 0 coreFailCount 0) { ElMessage.error(数据加载失败请稍后重试); } else { errors.forEach(msg ElMessage.error(msg)); } // 获取办理选项渐进加载 const activityInstance props.capitalAllocate?.activityInstance; if (activityInstance) { if (!isMounted || currentId ! requestId) return; getAuditOption(activityInstance) .then((result) { if (!isMounted || currentId ! requestId) return; auditOption.value result.data; }) .catch((error) { if (!isMounted || currentId ! requestId) return; console.error(获取办理选项失败:, error); }); } } catch (error) { console.error(请求过程发生意外错误, error); ElMessage.error(系统错误请稍后重试); } finally { if (isMounted currentId requestId) loading.value false; } };优点逻辑集中错误处理与请求配置解耦维护时只需修改配置数组。可扩展性强新增请求只需在requests中添加一项。清晰统计核心数据状态统一判断是否需要显示“整体失败”。方案二使用辅助函数处理单个请求结果定义一个小函数handleRequestResult专门处理单个 Promise 的结果并返回是否成功。然后在主函数中调用。代码示例typescriptconst fetchData async (id: number, workflowInstanceId: number, activityId: number) { const currentId requestId; loading.value true; try { // 并发请求 const [detailResult, fieldResult, auditResult] await Promise.allSettled([ capitalAllocateApi.getAllocateDetail(id), getActivityEditableFieldList(activityId), getAuditInfoList(workflowInstanceId) ]); if (!isMounted || currentId ! requestId) return; // 辅助函数处理单个结果返回是否成功fulfilled且有数据 const handleResult (result: PromiseSettledResultany, ref: any, errorMsg: string): boolean { if (result.status fulfilled result.value?.data) { ref.value result.value.data; return true; } else { return false; } }; // 处理核心数据 const detailOk handleResult(detailResult, allocateDatas, 资金分配明细加载失败); const auditOk handleResult(auditResult, auditDatas, 审核信息加载失败); // 处理非核心数据 handleResult(fieldResult, editableFieldDatas, 可编辑字段加载失败); await nextTick(); dataLoaded.value true; isModified.value false; // 核心数据判断 if (!detailOk !auditOk) { ElMessage.error(数据加载失败请稍后重试); } else { if (!detailOk) ElMessage.error(资金分配明细加载失败); if (!auditOk) ElMessage.error(审核信息加载失败); } // 获取办理选项同上 // ... } catch (error) { // ... } finally { // ... } };优点代码简洁减少了重复的if判断错误消息直接作为参数传递。保留原有结构仍使用Promise.allSettled和独立变量适合少量请求。推荐方案如果后续可能增加更多请求推荐方案一因为它将请求配置化更易于维护和扩展。如果请求数量固定且较少方案二更简单直接。两种方案都消除了冗余代码提高了可读性。其他注意点无论哪种方案都需要保留nextTick和竞态防护逻辑。渐进式加载的getAuditOption请求独立处理因为它依赖前面的结果且非核心保持原样即可。按照以上方式重构后fetchData将更加清晰错误处理逻辑集中且易于修改。优化后的代码// 发送网络请求获取数据 const fetchData async (id: number, workflowInstanceId: number, activityId: number) { const currentId requestId; loading.value true; try { // 并发请求 const [detailResult, fieldResult, auditResult] await Promise.allSettled([ // 获取资金分配明细列表 capitalAllocateApi.getAllocateDetail(id), // 获取活动可编辑字段 getActivityEditableFieldList(activityId), // 获取审批信息列表 getAuditInfoList(workflowInstanceId) ]); // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; // 辅助函数处理单个结果返回是否成功fulfilled且有数据 const handleResult (result: PromiseSettledResultany, ref: any, errorMsg: string): boolean { if (result.status fulfilled result.value?.data) { ref.value result.value.data; return true; } else { return false; } }; // 处理核心数据 const detailOk handleResult(detailResult, allocateDatas, 资金分配明细加载失败); const auditOk handleResult(auditResult, auditDatas, 审核信息加载失败); // 处理非核心数据 handleResult(fieldResult, editableFieldDatas, 可编辑字段加载失败); // 等待 watch 回调执行此时 dataLoaded 仍为 false不会错误修改 isModified await nextTick(); dataLoaded.value true; isModified.value false; // 核心数据判断 if (!detailOk !auditOk) { ElMessage.error(数据加载失败请稍后重试); } else { if (!detailOk) ElMessage.error(资金分配明细加载失败); if (!auditOk) ElMessage.error(审核信息加载失败); } // 渐进式加载核心数据先展示次要数据后加载获取办理选项 const activityInstance props.capitalAllocate?.activityInstance; if (activityInstance) { // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; getAuditOption(activityInstance) .then((result) { // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; auditOption.value result.data; }) .catch((error) { // 前置检查组件已卸载 或 不是当前最新请求则返回 if (!isMounted || currentId ! requestId) return; console.error(获取办理选项失败:, error); }); } } catch (error) { console.error(请求过程发生意外错误, error); ElMessage.error(系统错误请稍后重试); } finally { if (isMounted currentId requestId) loading.value false; } };

相关文章:

Vue3并发请求Promise.allSettled的结果处理优化示例

原来的代码:// 发送网络请求获取数据 const fetchData async (id: number, workflowInstanceId: number, activityId: number) > {const currentId requestId;loading.value true;try {// 并发请求const [detailResult, fieldResult, auditResult] await Pro…...

保姆级SAM 3入门指南:上传图片输入英文,轻松实现物体识别分割

保姆级SAM 3入门指南:上传图片输入英文,轻松实现物体识别分割 你是不是经常遇到这样的场景?看到一张精美的图片,想单独提取出里面的某个物体,比如一只可爱的猫、一本书,或者一个特别的Logo。手动抠图&…...

音频信号处理核心算法解析:从AEC到DOA的技术全景

1. 音频算法:从“听清”到“听懂”的智能进化 你有没有遇到过这样的尴尬场景?开视频会议时,自己的声音从对方音箱里传出来,又回到自己耳机,形成刺耳的回声循环,逼得大家只能轮流发言。或者,在嘈…...

NB-IoT模组QS100开发环境搭建与SDK实战指南

1. 从零开始:认识你的QS100 NB-IoT模组 大家好,我是老张,在物联网这行摸爬滚打十来年了,从早期的2G模块玩到现在各种NB-IoT、Cat.1,踩过的坑比走过的路还多。今天咱们不聊虚的,就手把手带你搞定QS100这个模…...

C++刷题实战:如何高效解决卡片配对问题(附完整代码解析)

从双指针到问题抽象:C实战中的“配对求和”思维跃迁 最近在辅导几位准备技术面试的朋友时,我发现一个有趣的现象:很多人对“双指针”这个经典技巧的理解,还停留在“知道有这么个方法”的层面。当遇到像“找出数组中所有和为特定值…...

DeOldify多模型效果对比:与原版及主流上色工具横向评测

DeOldify多模型效果对比:与原版及主流上色工具横向评测 老照片承载着记忆,但褪色的黑白影像总让人觉得少了些什么。过去,给老照片上色是件专业且耗时的工作,需要艺术家凭借经验和想象。如今,借助AI技术,我…...

Mish激活函数改进YOLOv26平滑非线性映射与自正则化特性双重突破

Mish激活函数改进YOLOv26平滑非线性映射与自正则化特性双重突破 摘要 在深度学习目标检测领域,激活函数作为神经网络的核心非线性组件,直接影响模型的表达能力和收敛性能。本文提出基于Mish激活函数的YOLOv26改进方案,通过引入平滑、无上界…...

91行代码创意赛技术文章大纲

比赛背景与意义91行代码创意赛的起源与目标,强调简洁性与创新性比赛对开发者技能提升的促进作用往届优秀作品的启发与参考价值参赛准备明确比赛规则与提交要求,确保代码不超过91行选择适合的编程语言与开发环境构思项目创意,平衡功能性与代码…...

HY-MT1.5-1.8B效果展示:1.8B小模型翻译质量媲美大模型

HY-MT1.5-1.8B效果展示:1.8B小模型翻译质量媲美大模型 1. 引言:小身材,大能量 在机器翻译的世界里,大家似乎形成了一个共识:模型越大,翻译质量越好。为了追求那一点点分数的提升,模型的参数量…...

CH549/CH548硬件设计避坑指南:Type-C接口与电源电路实战解析

CH549/CH548硬件设计避坑指南:Type-C接口与电源电路实战解析 最近在几个基于CH549和CH548的项目中,我遇到了不少关于Type-C接口和电源设计的“坑”。这些微控制器本身功能强大,性价比高,但在硬件设计上,尤其是围绕USB …...

StarRocks Stream Load 事务接口:两阶段提交机制深度解析

1. 为什么你需要关心Stream Load事务接口? 如果你正在用StarRocks做实时数仓,或者想把Kafka、Flink里的数据稳定高效地灌进StarRocks,那你肯定遇到过这样的头疼事:数据怎么老重复?导入性能上不去怎么办?任务…...

C语言实战:变位词统计的高效算法与函数设计

1. 从一道OJ题说起:变位词统计的“暴力”解法与性能陷阱 很多C语言初学者,包括当年刚接触编程的我,在拿到类似NWAFU-OJ上这道“变位词统计”的题目时,第一反应往往是“这不难”。题目要求很明确:给你一个文本字符串和一…...

JQ8400语音播报模块实战:从硬件连接到自定义语音(附Arduino示例代码)

JQ8400语音播报模块实战:从硬件连接到自定义语音(附Arduino示例代码) 你是否曾想过,让一个简单的电子项目“开口说话”?无论是制作一个会报时的智能闹钟,一个在传感器触发时发出语音警告的安防设备&#xf…...

ChatGPT VSCode 插件开发实战:从零构建你的AI编程助手

最近在尝试各种AI编程工具时,我萌生了一个想法:为什么不自己动手,在每天最熟悉的VSCode编辑器里,打造一个专属的AI编程助手呢?这样既能深度定制功能,又能把ChatGPT的能力无缝嵌入到编码工作流中。经过一番摸…...

scrapy-docs-l10n

Scrapy 文档的本地化🎉 scrapy-docs-l10n 已发布! 🚀 预览翻译:https://projects.localizethedocs.org/scrapy-docs-l10n 🌐 Crowdin:https://localizethedocs.crowdin.com/scrapy-docs-l10n &#x1f4…...

告别“古典加密时代”:2026价值共识重构,Cber携CMC以“随心而易,资产无界”破局

时间推移至2026年,当我们翻开加密货币市场的最新数据时,一种强烈的“割裂感”扑面而来:一方面,比特币和以太坊的ETF在华尔街的推波助澜下屡创新高,机构资金如潮水般涌入,加密市场总市值突破了前所未有的天际…...

Flutter 组件 build_cli_annotations 的适配 鸿蒙Harmony 实战 - 驾驭注解驱动 CLI 生成、实现鸿蒙端参数自动化审计与命令行交互效能方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net Flutter 组件 build_cli_annotations 的适配 鸿蒙Harmony 实战 - 驾驭注解驱动 CLI 生成、实现鸿蒙端参数自动化审计与命令行交互效能方案 前言 在鸿蒙(OpenHarmony&#xff0…...

Java从入门到精通(四):异常处理实战(Exception体系、全局处理与日志落地)

Java从入门到精通(四):异常处理实战(Exception体系、全局处理与日志落地)这是“Java从入门到精通”系列第4篇。前面我们讲了语法、面向对象、集合,这篇进入工程开发中最容易被忽略却最关键的一环&#xff1…...

工业软件中粗暴滤波 + 防漂移 + 防传感器突变的策略概述

工业软件中粗暴滤波 防漂移 防传感器突变的策略概述 在工业软件(如过程控制、传感器数据处理、自动化系统)中,传感器数据往往受到噪声、漂移(长期缓慢变化)和突变(尖峰或瞬变异常)的影响。这些…...

SpringBoot分层概念澄清 DTO、BO、VO

spring boot项目中: DTO就是前端到控制层 BO就是数据库到服务层 VO就是服务层到前端这样理解是否正确?在Spring Boot项目中,关于DTO、BO和VO的划分确实存在一些常见约定,但你的理解中有些地方需要进一步澄清。下面是对这些概念在典型分层架构…...

计算机毕业设计springboot汽车租赁系统 SpringBoot框架下智能车辆分时租赁与调度服务平台 基于Java Web的共享汽车在线预约与运维管理系统

计算机毕业设计springboot汽车租赁系统m9112h75(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着居民出行需求的多元化与共享经济的蓬勃发展,汽车租赁行业正从传统…...

【effective C++】条款四十四:将与参数无关的代码抽离 templates

文章目录Effective C 条款44:将与参数无关的代码抽离templates核心思想:对抗"代码膨胀"规则详解与示例规则1:不与造成膨胀的参数相依规则2:处理非类型参数造成的膨胀规则3:处理类型参数造成的膨胀优化带来的…...

【第二周】论文精读:REPLUG: Retrieval-Augmented Black-Box Language Models

前言:随着大语言模型(LLM)规模的爆炸式增长(如 GPT-3, Codex 等参数量超千亿的模型),它们大多以“黑盒”API 的形式提供服务,用户无法访问其内部参数或进行微调。这使得传统的检索增强方法&…...

Mybatis进阶(一)

一、MyBatis 基于接口代理方式实现 Dao 层开发1.1 介绍采用 Mybatis 的基于接口代理方式实现 持久层 的开发,这种方式是我们后面进入企业的主流。 基于接口代理方式的开发只需要程序员编写 Mapper 接口,Mybatis 框架会为我们动态生成实现类的对象。1.2 开…...

[协程]-[详解]-launch与async

launch作用构建一个协程, 直接返回Job使用// lifecycleScope 协程作用域 lifecycleScope.launch { // 启动一个父协程delay(10000) // 模拟任务耗时 }源码解析public fun CoroutineScope.launch(context: CoroutineContext EmptyCoroutineContext,start: CoroutineStart Coro…...

开发者在 CSDN 的“修行”过程

目录 第一阶段:踩坑与复盘(底层输出) 第二阶段:CSDN 发帖逻辑(流量密码) 第三阶段:高阶答疑(建立信任) 第四阶段:涨粉与影响力变现(全链路总结…...

采购报销-发票预制及过账 增强供应商应付按订单行

1、术语发票校验:采购发票是供应商开给购货单位,据以付款、记账、纳税的依据。参照采购订单和采购入库单,按内容、价格进行发票正确性检查。一张发票过帐时,系统在供货商帐中创建一个未清项目,然后由财务会计在支付中结…...

OpenClaw 小龙虾保姆级安装教程

OpenClaw 小龙虾保姆级安装教程 小白 10 分钟搞定本地部署(Windows 系统 - 接入飞书) 引言 OpenClaw 最近实在是太火了,很多人已经做起了上门安装 500 块一次的生意,甚至有人计算下来说,靠这门手艺有机会年收入百万…...

安卓wakelock 学习

目录 1, wakelock 是什么 2,如何使用wakelock 3, 安卓系统中使用wakelock 的实例 4, 实际项目中wakelock 遇到的问题 1, wakelock 是什么 Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠&…...

MySQL【表的约束上】

一、表的约束在 MySQL 数据库的使用过程中,我们会发现仅靠数据类型来限制字段远远不够 —— 数据类型的约束能力单一,无法从业务逻辑层面保证数据的正确性。比如要求用户表的邮箱字段唯一、订单表的用户 ID 必须关联存在的用户,这些需求都需要…...