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

Promise 简单介绍及深入挖掘

一、什么是 Promise?

在 JavaScript 中,Promise 是用于处理异步操作的一种方式。它代表了一个 可能 在将来某个时间点完成或失败的操作的结果。Promise 使得我们能够优雅地处理异步代码,避免了回调地狱(Callback Hell)的问题,提升了代码的可读性和可维护性。

  • Promise 的基本状态
    • Pending(进行中): 初始状态,表示异步操作还未完成。
    • Fulfilled(已完成): 表示异步操作已成功完成
    • Rejected(已拒绝): 表示异步操作失败

二、Promise 的基本用法

  1. 创建 Promise

Promise 是通过构造函数创建的,new Promise() 接受一个执行器函数作为参数,该函数有两个参数:resolve 和 reject,分别用于处理成功和失败的情况

let promise = new Promise((resolve, reject) => {// 异步操作let success = true; // 假设这是异步操作的结果if (success) {resolve("操作成功");} else {reject("操作失败");}
});
  1. 使用 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 的实现原理

  1. Promise 的状态机

    • Promise 的状态是由内部的状态机管理的,状态一旦改变就不能再改变。状态流转的规则如下

      • Pending(进行中)Fulfilled(已完成):当异步操作成功时,调用 resolve() 方法,Promise 进入 Fulfilled 状态。
      • Pending(进行中)Rejected(已拒绝):当异步操作失败时,调用 reject() 方法,Promise 进入 Rejected 状态。

状态的转变是 不可逆的,即一旦从 Pending 状态变成了 Fulfilled 或 Rejected,就不能再回到 Pending 状态。

  1. 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
  2. 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 的状态和结果‌。

      • 工作原理

        1. 参数‌:接受一个 Promise 数组或可迭代对象作为参数。
        2. 行为‌:返回一个新的 Promise 对象。一旦传入的 Promise 数组中的任何一个 Promise 解决或拒绝,返回的 Promise 就会采用那个 Promise 的状态和结果。
        3. 状态‌:如果第一个完成的 Promise 是解决状态,返回的 Promise 也是解决状态;如果是拒绝状态,返回的 Promise 也是拒绝状态‌12。
      • 使用场景

        1. ‌竞争条件‌:当多个异步操作可能同时完成,但你只需要第一个完成的结果时。
        2. 超时处理‌:可以将一个超时操作与实际的操作放在同一个 race 中,确保在超时后能够及时处理。
        3. 事件监听‌:在多个事件监听器中,只需要第一个触发的事件的处理结果。
           // 定义两个异步操作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?

  1. 避免回调地狱:传统的回调函数(Callback)可能会出现嵌套问题,导致代码难以理解和维护。使用 Promise 可以避免嵌套回调。
  2. 更好的错误处理:Promise 使得错误处理变得简单,使用 catch() 可以统一处理异常。
  3. 链式调用:多个异步操作可以通过链式调用的方式实现顺序执行。
  4. 并发操作管理:通过 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 • 数据只有在设计的场景中才有意义。&#xff…...

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中&#xff0c;std::list 是一个双向链表&#xff0c;它允许在列表的任何位置高效地插入和删除元素。以下是一些基本的使用方式&#xff1a; 包含头文件 要使用 std::list&#xff0c;首先需要包含头文件 <iostream> 和 /list>。 #include <iostream> #in…...

nginx配置代理地址

1&#xff0c;配置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&#xff0c;由清华大学和北京大学共同创建的AndroidLab数据集&#xff0c;为安卓自主代理的训练和评估提供了一个包含操作环境、行动空间和可复现基准的系统框架&#xff0c;这对于推动安卓代理技术的发展具有重要意义。 数据集地址&#xff1a;Android Instruct|A…...

Java--正则表达式入门指南

正则表达式&#xff08;Regular Expression&#xff09;是一种用于匹配字符串中字符模式的工具。在Java中&#xff0c;正则表达式的使用主要依赖于java.util.regex包&#xff0c;其中最重要的两个类是Pattern和Matcher。今天将探讨正则表达式的基础概念、书写规则、常用方法&am…...

阿里云服务器 篇十(加更二):自动定时备份CSDN博客内容:更新文件最后修改时间,以在个人博客正确展示最近更新

文章目录 系列文章核心修改更新后的核心代码使用方法系列文章 阿里云服务器 篇一:申请和初始化 阿里云服务器 篇二:搭建静态网站 阿里云服务器 篇三:提交搜索引擎收录 阿里云服务器 篇四:404页面模板 阿里云服务器 篇五:短链服务网站 阿里云服务器 篇六:GitHub镜像网站 …...

Python编程探索:从基础语法到循环结构实践

文章目录 前言1. 行与缩进&#xff1a;Python代码的灵魂2. 数据类型的转换&#xff1a;灵活处理数据3. 字符串切片&#xff1a;提取字符串的子部分4. 字符串拼接&#xff1a;连接多个字符串5. 逻辑运算符&#xff1a;处理布尔值6. 成员运算符&#xff1a;检查值是否存在于序列中…...

今天要重新认识下注解@RequestBody

在Spring框架中&#xff0c;RequestBody是一个常用的注解&#xff0c;它用于将HTTP请求体中的数据绑定到控制器&#xff08;Controller&#xff09;处理方法的参数上。这个注解通常与RESTful Web服务一起使用&#xff0c;在处理POST或PUT请求时尤为常见&#xff0c;因为这些请求…...

北斗有源终端|智能5G单北斗终端|单兵|单北斗|手持机

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

【题解】—— LeetCode一周小结44

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结43 28.冗余连接 II 题目链接&#xff1a;685. 冗余连接 II 在…...

faiss 用于检索10亿向量(维度768)的方法

faiss 用检索10亿向量(维度768)的方法,注意考虑占用内存空间大小不能超过100G,因为100G已经是很多服务器内存的极限了,有的128G已经是超规格的机器了。价格也就是2000左右(月租)。 要处理 10 亿个 768 维的向量,并且限制内存占用不超过 100G,我们需要使用 FAISS 中的…...

sql专题 之 常用命令

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

Kubernetes Extended Resource 扩展资源使用简介

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

基于STM32的天气时钟项目教学

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

神经网络进行波士顿房价预测

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

C++builder中的人工智能(7)如何在C++中开发特别的AI激活函数?

在当今的AI开发中&#xff0c;人工智能模型正迅速增加。这些模型使用数学函数来执行和学习&#xff0c;以便在传播时优化最佳结果&#xff0c;或在反向传播时选择最佳解决方案。其中之一就是激活函数。也称为转移函数或阈值函数&#xff0c;它决定了神经元的激活值作为输出&…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...

第22节 Node.js JXcore 打包

Node.js是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。 JXcore是一个支持多线程的 Node.js 发行版本&#xff0c;基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。 本文主要介绍JXcore的打包功能。 JXcore 安装 下载JXcore安装包&a…...