07-使用 JavaScript Promise 并行处理多个请求

使用 JavaScript Promise 并行处理多个请求

笔记+分享
在现代Web开发中,处理多个异步请求并行是一个常见需求。JavaScript中的Promise提供了一种强大的机制来管理这些并行操作。本文将详细介绍如何使用Promise.allPromise.allSettled来实现这一点,并提供一些实用的示例代码。

Promise.all 和 Promise.allSettled

在处理多个并行请求时,最常用的两个Promise方法是Promise.allPromise.allSettled

Promise.all

Promise.all方法接收一个Promise数组,当所有Promise都成功时,返回一个包含所有结果的数组。如果任何一个Promise失败,整个Promise.all都会立即失败,并抛出第一个失败的Promise的错误。

const promise1 = new Promise((resolve) => {setTimeout(() => resolve('Promise 1 resolved'), 1000);
});const promise2 = new Promise((resolve) => {setTimeout(() => resolve('Promise 2 resolved'), 2000);
});const promise3 = new Promise((_, reject) => {setTimeout(() => reject('Promise 3 rejected'), 1500);
});Promise.all([promise1, promise2, promise3]).then(results => {console.log(results); // 不会执行}).catch(error => {console.error(error); // 输出: Promise 3 rejected});

在这个例子中,Promise.all因为promise3被拒绝而失败,导致整个操作被短路。

Promise.allSettled

相比之下,Promise.allSettled方法会等待所有Promise都完成,无论是成功还是失败。它返回一个包含每个Promise结果对象的数组,每个结果对象都有一个status属性(“fulfilled"或"rejected”)和相应的valuereason属性。

Promise.allSettled([promise1, promise2, promise3]).then(results => {results.forEach((result, index) => {if (result.status === 'fulfilled') {console.log(`Promise ${index + 1} fulfilled with value: ${result.value}`);} else {console.error(`Promise ${index + 1} rejected with reason: ${result.reason}`);}});});

在这个例子中,所有Promise的状态都会被处理,无论它们是成功还是失败。

使用 Promise.all 实现错误处理

虽然Promise.allSettled可以处理所有Promise的结果,无论它们是否成功或失败,但有时我们更希望使用Promise.all,但又不想因为某个Promise失败而导致所有Promise都被短路。为了解决这个问题,我们可以通过在每个Promise周围添加一个错误处理逻辑来实现。这可以通过在每个Promise后添加.catch来捕获错误并返回一个标记为失败的结果对象。

包装 Promise 以处理错误

我们可以创建一个包装函数,确保所有Promise都能执行,并返回一个包含结果和错误的数组。

const handlePromise = (promise) => {return promise.then(result => ({ status: 'fulfilled', value: result })).catch(error => ({ status: 'rejected', reason: error }));
};const fetchUser = fetch('https://api.example.com/user').then(res => res.json());
const fetchPosts = fetch('https://api.example.com/posts').then(res => res.json());
const fetchComments = fetch('https://api.example.com/comments').then(res => res.json());Promise.all([handlePromise(fetchUser),handlePromise(fetchPosts),handlePromise(fetchComments)
])
.then(results => {results.forEach((result, index) => {if (result.status === 'fulfilled') {console.log(`Request ${index + 1} succeeded with value:`, result.value);} else {console.error(`Request ${index + 1} failed with reason:`, result.reason);}});
});

详细示例

假设我们有三个并行的API请求,即使其中一个请求失败,我们仍然希望其他请求能够完成并处理它们的结果或错误。

const handlePromise = (promise) => {return promise.then(result => ({ status: 'fulfilled', value: result })).catch(error => ({ status: 'rejected', reason: error }));
};// 示例请求
const fetchUser = fetch('https://api.example.com/user').then(response => {if (!response.ok) {throw new Error('Failed to fetch user');}return response.json();
});const fetchPosts = fetch('https://api.example.com/posts').then(response => {if (!response.ok) {throw new Error('Failed to fetch posts');}return response.json();
});const fetchComments = fetch('https://api.example.com/comments').then(response => {if (!response.ok) {throw new Error('Failed to fetch comments');}return response.json();
});// 使用 Promise.all 执行所有请求
Promise.all([handlePromise(fetchUser),handlePromise(fetchPosts),handlePromise(fetchComments)
])
.then(results => {results.forEach((result, index) => {if (result.status === 'fulfilled') {console.log(`Request ${index + 1} succeeded with value:`, result.value);} else {console.error(`Request ${index + 1} failed with reason:`, result.reason);}});
});

解析

  1. handlePromise 函数:该函数接收一个Promise,并在Promise解析或拒绝时返回一个标准化的对象,包含statusvaluereason
  2. 并行请求:每个请求通过fetch方法发起,并附带错误处理。如果请求失败,抛出一个错误。
  3. Promise.all:使用Promise.all并行执行所有经过handlePromise包装的请求。即使其中一个或多个请求失败,所有请求都会继续执行。
  4. 结果处理:在then方法中,遍历所有结果,根据status属性分别处理成功和失败的请求。

总结

通过这种方式,使用Promise.all时,可以确保所有Promise都能执行,无论其中某些Promise是否失败。这在处理多个并行请求时非常有用,可以确保即使某些请求失败,也能获取其他请求的结果,从而提高代码的健壮性和可靠性。希望本文的介绍和示例代码能够帮助你更好地理解和使用JavaScript中的Promise来管理并行请求。


通过这种方式,开发者可以更灵活地处理并行请求,无论是使用Promise.all还是Promise.allSettled,都能够确保在复杂的异步操作中更加健壮地管理请求结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/22406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Echarts 中type是value的X轴在设置了interval间隔后没有展示

文章目录 问题分析问题 Echarts中type是value的X轴在设置了interval间隔后没有展示 分析 之前代码是这样写的:axisLabel 属性中设置了 interval ,但未起作用,原因如下 在 ECharts 中,interval 属性是用于类目型(category)轴的刻度间隔设置,并不适用于数值型(value)…

音视频视频点播

视频点播是集音视频采集,编辑,上传,自动化转码处理,媒体资源管理,高效云剪辑处理,分发加速,视频播放于一体的一站式音视频点播解决方案 阿里云视频点播基于阿里云强大的基础设施服务&#xff0c…

解决 clickhouse jdbc 偶现 failed to respond 问题

背景 Clickhouse集群版本为 Github Clickhouse 22.3.5.5, clickhouse-jdbc 版本为 0.2.4。 问题表现 随着业务需求的扩展,基于Clickhouse 需要支持更多任务在期望的时效内完成,于是将业务系统和Clickhouse交互的部分都提交给可动态调整核心…

【西瓜书】1.绪论

1.基本术语 (1)数据集不带最后一列:样本/示例/特征向量 带最后一列:样例 (2)表头不带最后一列:属性/特征,属性空间/特征空间/样本空间/输入空间 表头最后一列:标记/输出…

windows上安装MongoDB,springboot整合MongoDB

上一篇文章已经通过在Ubuntu上安装MongoDB详细介绍了MongoDB的各种命令用法。 Ubuntu上安装、使用MongoDB详细教程https://blog.csdn.net/heyl163_/article/details/133781878 这篇文章介绍一下在windows上安装MongoDB,并通过在springboot项目中使用MongoDB记录用户…

Go语言交叉编译

Golang 支持交叉编译, 在一个平台上生成然后再另外一个平台去执行。 以下面代码为例 build ├── main.go ├── go.mod main.go内容 package mainimport "fmt"func main() {fmt.Println("hello world") }windows系统上操作 1.cmd窗口编译…

java新特性--03-1--Stream---Collectors工具类

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1.stream 收集Collectors工具类注意区分 Collections工具类 练习1:查找工资大于6000的员工,结果返回为一个List练习2:查找年龄小…

【含项目亮点】小免鲜项目总结

【含项目亮点】小兔鲜项目总结 基础总结 vue3的优势 组合式API,更好的支持TS。速度提高,diff算法重写。按需引入,更好的treeshaking,体积小。数据式响应更优,使用js的proxy替代Object.defineProperty数据响应式系统,更灵活。 vue3使用的是vue-create脚手架工具,vue2使用…

【设计模式】结构型-组合模式

前言 在软件开发中,设计模式是一种被广泛应用的解决问题的方法论。其中,结构性设计模式是一类特别重要的模式,它们用于处理类或对象之间的组合关系,其中之一就是组合模式。组合模式允许客户端统一对待单个对象和对象的组合&#…

结构体(2),链表,共用体

链式数据结构 -- 链表 定义: struct Node { int data; //数据域 --存储要处理的数据 struct Node *next; //指针域,保存地址-- 指向下一个节点 }; //数据域指针域 //节点类型 struct Node n1; struct Node n2; struct Node n3; s1--&…

DeepSort整体流程梳理及匈牙利算法解析

文章目录 算法原理一、主要步骤二、算法流程:三、匈牙利算法:3.1 举例说明匈牙利匹配过程:3.2匈牙利算法中代价矩阵的计算(距离)卡尔曼滤波后面更新。 算法原理 DeepSort核心在于其对目标的外观特征和运动特征的联合使用,以及对目标匹配问题的优化处理。该算法通过融合目…

【前端技术】 ES6 介绍及常用语法说明

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…

使用wheelnav.js构建酷炫的动态导航菜单

目录 前言 一、WheelNav是什么 1、项目地址 2、关于开源协议 3、相关目录介绍 二、如何使用wheelnav.js 1、新建html页面 2、设置style样式 3、创建展示元素实现动态导航 三、参数即方法介绍 1、参数列表 2、运行方法 3、实际成果 四、总结 前言 用户体验永远是一…

玩转盲盒潮流:从0到1搭建小程序平台

玩转盲盒潮流并搭建一个从0到1的小程序平台来创作内容是一个充满挑战但有趣的过程。以下是一个步骤指南,帮助你实现这一目标: 1. 市场调研与定位 了解盲盒市场:研究当前盲盒市场的趋势、消费者喜好和成功案例。确定目标用户:明确…

android-jni2

详细的jni调用说明:Android学习--JNI_android jni-CSDN博客 jclass clazz;index;LOGE("开始:%d", "begin");clazz (*env).FindClass("com/changan/incalleventservice/input/NativeAction");//找到对应的java文件jfieldID instanc…

docker-compose 部署rabbitmq 15672打不开

docker-compose 部署rabbitmq 15672打不开 如果docker-compose的rabbitmq镜像后缀不是-management如:3.7.4-management,则需要进入容器中手动启动插件 部署rabbitmq后需要启动插件的命令: rabbitmq-plugins enable rabbitmq_management 一…

软件质量保障——三、四

三、黑盒测试 1.黑盒测试概述 1.1 如何理解黑盒测试? 1.2 黑盒测试有什么特点? 1.3 如何实施黑盒测试? 2. 黑盒测试用例设计和生成方法(这里还是要自己找题做) 2.1 等价类划分法 步骤: 1.选择划分准…

解释JDBC的作用和连接数据库的步骤

JDBC(Java Database Connectivity)是Java编程语言中用来执行SQL语句的API。它的主要作用是为Java程序提供连接各种关系型数据库的能力,使得Java开发者能够编写出与数据库进行交互的应用程序。JDBC的作用具体体现在以下几个方面: 数…

在多支付渠道中这个设计模式无敌好用!

假设我们有一个电商平台,需要支持多种支付方式。 通过策略模式来实现,管理不同的支付方式,并根据需求快速添加新的支付方式。 定义支付策略接口及其实现类: // 支付策略接口 public interface PaymentStrategy { void pay(int …

SASS基础知识

什么是SASS 1. SASS与CSS的关系 SASS(Syntactically Awesome Stylesheets)是一种强大的CSS扩展语言,它允许开发者使用变量、嵌套规则、混合宏和更多功能,这些在纯CSS中是不可能做到的。SASS旨在简化CSS代码的维护,并…