Promise 简单介绍及深入挖掘
一、什么是 Promise?
在 JavaScript 中,Promise 是用于处理异步操作的一种方式。它代表了一个 可能 在将来某个时间点完成或失败的操作的结果。Promise 使得我们能够优雅地处理异步代码,避免了回调地狱(Callback Hell)的问题,提升了代码的可读性和可维护性。
- Promise 的基本状态
- Pending(进行中): 初始状态,表示异步操作还未完成。
- Fulfilled(已完成): 表示异步操作已成功完成
- Rejected(已拒绝): 表示异步操作失败
二、Promise 的基本用法
- 创建 Promise
Promise 是通过构造函数创建的,new Promise() 接受一个执行器函数作为参数,该函数有两个参数:resolve 和 reject,分别用于处理成功和失败的情况
let promise = new Promise((resolve, reject) => {// 异步操作let success = true; // 假设这是异步操作的结果if (success) {resolve("操作成功");} else {reject("操作失败");}
});
-
使用 then() 和 catch() 处理结果
- then() 用于处理成功的结果。
- catch() 用于处理失败的结果。
promise.then(result => {console.log(result); // 输出:操作成功}).catch(error => {console.log(error); // 输出:操作失败});
三、Promise 链式调用
let promise = new Promise((resolve, reject) => {resolve(1);
});promise.then(result => {console.log(result); // 输出:1return result + 1; // 返回新的值}).then(result => {console.log(result); // 输出:2return result + 2;}).then(result => {console.log(result); // 输出:4});
四、深入挖掘:Promise 的实现原理
-
Promise 的状态机
-
Promise 的状态是由内部的状态机管理的,状态一旦改变就不能再改变。状态流转的规则如下
- 从 Pending(进行中) 到 Fulfilled(已完成):当异步操作成功时,调用 resolve() 方法,Promise 进入 Fulfilled 状态。
- 从 Pending(进行中) 到 Rejected(已拒绝):当异步操作失败时,调用 reject() 方法,Promise 进入 Rejected 状态。
-
状态的转变是 不可逆的,即一旦从 Pending 状态变成了 Fulfilled 或 Rejected,就不能再回到 Pending 状态。
-
Promise 的微任务队列
在 JavaScript 的事件循环(Event Loop)中,Promise 的回调函数(即 then() 或 catch() 中的回调函数)被放入 微任务队列(Microtask Queue) 中,优先于宏任务队列(比如 setTimeout() 和 setInterval())执行。
- 当同步代码执行完毕后,事件循环会检查微任务队列。
- 微任务队列中的任务会被优先执行,直到队列为空,然后才会继续处理宏任务队列。
console.log("同步任务 1");let promise = new Promise((resolve, reject) => {resolve("异步任务 1");});promise.then(result => {console.log(result); // 输出:异步任务 1});console.log("同步任务 2");// 输出顺序:同步任务 1 -> 同步任务 2 -> 异步任务 1
-
Promise 解决并发问题:Promise.all 和 Promise.race
-
Promise.all()
接受一个 Promise 对象的数组,并返回一个新的 Promise。当所有传入的 Promise 都成功完成时,返回的 Promise 也会成功,并将所有 Promise 的结果作为一个数组返回;如果任何一个 Promise 失败,返回的 Promise 会立即失败,并以第一个失败的 Promise 的错误信息为失败原因
let p1 = new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p1')); let p2 = new Promise((resolve, reject) => setTimeout(resolve, 2000, 'p2')); let p3 = new Promise((resolve, reject) => setTimeout(resolve, 3000, 'p3'));Promise.all([p1, p2, p3]).then(results => {console.log(results); // 输出:['p1', 'p2', 'p3']}).catch(error => {console.log(error);});
注意事项: Promise.all() 会以第一个失败的 Promise 的错误信息为失败原因,而不是所有失败的错误信息。如果需要处理每个 Promise 的错误,可能需要使用其他方法或结合 Promise.allSettled()。
-
Promise.allSettled()
用于并行执行多个Promise对象,并在所有Promise对象都完成(无论是成功还是失败)后返回一个包含所有Promise结果的数组。与Promise.all不同的是,Promise.allSettled不会在遇到第一个失败的Promise时立即返回,而是会等待所有Promise都完成后返回结果
-
返回值
-
status:表示Promise的状态,可能的值为“fulfilled”(已解决)或“rejected”(已拒绝)
-
value:如果Promise已解决,则为解决值;如果Promise已拒绝,则为拒绝原因
const promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 1 resolved');}, 2000); });const promise2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 2 resolved');}, 1000); });const promise3 = new Promise((resolve, reject) => {setTimeout(() => {reject('Promise 3 rejected');}, 1500); });Promise.allSettled([promise1, promise2, promise3]).then(results => {results.forEach(result => {if (result.status === 'fulfilled') {console.log('Resolved:', result.value);} else if (result.status === 'rejected') {console.log('Rejected:', result.reason);}});});
-
-
-
Promise.race()
用于解决一组 Promise 中最早解决或拒绝的 Promise。它接受一个 Promise 数组或可迭代对象作为参数,返回一个新的 Promise 对象。这个新返回的 Promise 会采用第一个完成(无论是解决还是拒绝)的 Promise 的状态和结果。
-
工作原理
- 参数:接受一个 Promise 数组或可迭代对象作为参数。
- 行为:返回一个新的 Promise 对象。一旦传入的 Promise 数组中的任何一个 Promise 解决或拒绝,返回的 Promise 就会采用那个 Promise 的状态和结果。
- 状态:如果第一个完成的 Promise 是解决状态,返回的 Promise 也是解决状态;如果是拒绝状态,返回的 Promise 也是拒绝状态12。
-
使用场景
- 竞争条件:当多个异步操作可能同时完成,但你只需要第一个完成的结果时。
- 超时处理:可以将一个超时操作与实际的操作放在同一个 race 中,确保在超时后能够及时处理。
- 事件监听:在多个事件监听器中,只需要第一个触发的事件的处理结果。
// 定义两个异步操作const p1 = new Promise((resolve, reject) => setTimeout(() => resolve('p1'), 500));const p2 = new Promise((resolve, reject) => setTimeout(() => reject('p2'), 300));// 使用 Promise.race()Promise.race([p1, p2]).then((result) => {console.log(result); }).catch((error) => {console.log(error); // 'p2',因为 p2 先拒绝});// 在这个例子中,p2 是第一个被拒绝的 Promise,因此 catch() 被调用并打印 'p2'。
-
-
五、为什么要使用 Promise?
- 避免回调地狱:传统的回调函数(Callback)可能会出现嵌套问题,导致代码难以理解和维护。使用 Promise 可以避免嵌套回调。
- 更好的错误处理:Promise 使得错误处理变得简单,使用 catch() 可以统一处理异常。
- 链式调用:多个异步操作可以通过链式调用的方式实现顺序执行。
- 并发操作管理:通过 Promise.all() 或 Promise.race() 可以更方便地管理多个异步任务的并发执行。
相关文章:
Promise 简单介绍及深入挖掘
一、什么是 Promise? 在 JavaScript 中,Promise 是用于处理异步操作的一种方式。它代表了一个 可能 在将来某个时间点完成或失败的操作的结果。Promise 使得我们能够优雅地处理异步代码,避免了回调地狱(Callback Hell)…...

103 - Lecture 1
Introduction to Database 一、Introduction to Database Systems 1. 数据的定义 What is Data? EX: data could be a docx file storing your project status report; data could be a spreadsheet containing information • 数据只有在设计的场景中才有意义。ÿ…...
Ubuntu 20.04禁用或者移除 cloud-init
1、禁用cloud-init 这是最简单最安全的方法,在 /etc/cloud 目录下创建 cloud-init.disabled 文件重启后生效。删除该文件就可以恢复 # 创建cloud-init.disabled文件 sudo touch /etc/cloud/cloud-init.disabled # 重启 reboot 2、移除 cloud-init 软件包及文件夹…...

DevOps开发运维简述
DevOps平台是一套集成的解决方案,旨在协调软件开发(Development)和信息技术运维(Operations)。它促进跨功能团队合作,实现自动化流程,确保持续集成与持续交付(CI/CD)。 一…...
C++之list的使用
在C中,std::list 是一个双向链表,它允许在列表的任何位置高效地插入和删除元素。以下是一些基本的使用方式: 包含头文件 要使用 std::list,首先需要包含头文件 <iostream> 和 /list>。 #include <iostream> #in…...
nginx配置代理地址
1,配置19上的代理 location /jmis/ { alias D:/images/; autoindex on; sendfile on; } 2.在18服务器上访问19的图片。18服务器nginx代理 proxy_set_header 指令用于在发送给后端服务器的请求中添加或修改指定的HTTP头信息。 proxy_p…...

国际版JAVA同城打车源码同城服务线下结账系统源码适配PAD支持Android+IOS+H5
一、数据中心 总用户数今日接单数量今日新增今日收入本月新增本月收入本年新增本年收入 二、用户中心 全部用户普通用户师傅用户推广员用户 三、财务中心 提现管理收入统计提现统计充值统计充值记录保证金管理平台收入统计 四、首页装修 轮播图分享图语音播报配置 五…...

AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
2024-10-31,由清华大学和北京大学共同创建的AndroidLab数据集,为安卓自主代理的训练和评估提供了一个包含操作环境、行动空间和可复现基准的系统框架,这对于推动安卓代理技术的发展具有重要意义。 数据集地址:Android Instruct|A…...
Java--正则表达式入门指南
正则表达式(Regular Expression)是一种用于匹配字符串中字符模式的工具。在Java中,正则表达式的使用主要依赖于java.util.regex包,其中最重要的两个类是Pattern和Matcher。今天将探讨正则表达式的基础概念、书写规则、常用方法&am…...
阿里云服务器 篇十(加更二):自动定时备份CSDN博客内容:更新文件最后修改时间,以在个人博客正确展示最近更新
文章目录 系列文章核心修改更新后的核心代码使用方法系列文章 阿里云服务器 篇一:申请和初始化 阿里云服务器 篇二:搭建静态网站 阿里云服务器 篇三:提交搜索引擎收录 阿里云服务器 篇四:404页面模板 阿里云服务器 篇五:短链服务网站 阿里云服务器 篇六:GitHub镜像网站 …...
Python编程探索:从基础语法到循环结构实践
文章目录 前言1. 行与缩进:Python代码的灵魂2. 数据类型的转换:灵活处理数据3. 字符串切片:提取字符串的子部分4. 字符串拼接:连接多个字符串5. 逻辑运算符:处理布尔值6. 成员运算符:检查值是否存在于序列中…...

今天要重新认识下注解@RequestBody
在Spring框架中,RequestBody是一个常用的注解,它用于将HTTP请求体中的数据绑定到控制器(Controller)处理方法的参数上。这个注解通常与RESTful Web服务一起使用,在处理POST或PUT请求时尤为常见,因为这些请求…...

北斗有源终端|智能5G单北斗终端|单兵|单北斗|手持机
在当今科技日新月异的时代,智能设备的创新与升级速度令人目不暇接。其中,智能5G终端作为连接数字世界的桥梁,正逐步渗透到我们生活的方方面面。今天,让我们聚焦于一款集尖端科技与实用功能于一身的智能5G设备——QM-L5智能5G单北斗…...

【题解】—— LeetCode一周小结44
🌟欢迎来到 我的博客 —— 探索技术的无限可能! 🌟博客的简介(文章目录) 【题解】—— 每日一道题目栏 上接:【题解】—— LeetCode一周小结43 28.冗余连接 II 题目链接:685. 冗余连接 II 在…...
faiss 用于检索10亿向量(维度768)的方法
faiss 用检索10亿向量(维度768)的方法,注意考虑占用内存空间大小不能超过100G,因为100G已经是很多服务器内存的极限了,有的128G已经是超规格的机器了。价格也就是2000左右(月租)。 要处理 10 亿个 768 维的向量,并且限制内存占用不超过 100G,我们需要使用 FAISS 中的…...

sql专题 之 常用命令
文章目录 查询基础语法查询全表查询选择查询:常量和运算: 条件查询where运算符:、 !、<、>空值:null模糊查询:like逻辑运算:and or not 去重:distinct排序:order by截断和偏移…...

Kubernetes Extended Resource 扩展资源使用简介
Kubernetes 除了提供基于 CPU 和内存的传统计算资源调度外,还支持自定义的 Extended Resource 扩展资源,以便调度和管理其它各种类型的资源。 Extended Resource Extended Resource 扩展资源的创建和使用过程如下图所示: 定义资源ÿ…...

基于STM32的天气时钟项目教学
引言 随着物联网技术的普及,基于STM32的微控制器被广泛应用于各种智能设备的开发。本项目旨在打造一个基于STM32的天气时钟,除了显示当前时间,还可以通过Wi-Fi获取当地天气信息,提供一个实用的生活工具。 环境准备 在开始项目之前…...

神经网络进行波士顿房价预测
前言 前一阵学校有五一数模节校赛,和朋友一起参加做B题,波士顿房价预测,算是第一次自己动手实现一个简单的小网络吧,虽然很简单,但还是想记录一下。 题目介绍 波士顿住房数据由哈里森和鲁宾菲尔德于1978年Harrison …...

C++builder中的人工智能(7)如何在C++中开发特别的AI激活函数?
在当今的AI开发中,人工智能模型正迅速增加。这些模型使用数学函数来执行和学习,以便在传播时优化最佳结果,或在反向传播时选择最佳解决方案。其中之一就是激活函数。也称为转移函数或阈值函数,它决定了神经元的激活值作为输出&…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...