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() 可以更方便地管理多个异步任务的并发执行。

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

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

相关文章

springboot2.x使用SSE方式代理或者转发其他流式接口

文章目录 1.需求描述2.代码2.1.示例controller2.2.示例service2.3.示例impl 3.测试 1.需求描述 使用SSE的方式主要还是要跟前端建立一个EventSource的链接,有了这个连接,然后往通道里写入数据流,前端自然会拿到流式数据,写啥拿啥…

Java学习教程,从入门到精通,Java方法语法的知识点总结(21)

1、Java方法语法的知识点总结 方法定义: 方法是执行特定任务的代码块。 方法包含一个方法头和一个方法体。 语法: [修饰符] 返回值类型 方法名(参数列表) {// 方法体 }修饰符: 访问修饰符(如 public, private, protected&#x…

Hive操作库、操作表及数据仓库的简单介绍

数据仓库和数据库 数据库和数仓区别 数据库与数据仓库的区别实际讲的是OLTP与OLAP的区别 操作型处理(数据库),叫联机事务处理OLTP(On-Line Transaction Processing),也可以称面向用户交易的处理系统,它是针对具体业务…

C#语言在软件开发中的应用与优势

C#(读作“C-sharp”)是一种由微软公司开发的通用高级编程语言,自2000年发布以来,它迅速成为开发人员构建各种类型应用程序的首选语言之一。C#的设计目标是成为一种简单、现代、面向对象的语言,它结合了C的强大功能和Ja…

基于STM32的智能植物灌溉系统设计

引言 本项目基于STM32微控制器设计了一个智能植物灌溉系统,通过集成土壤湿度传感器和水泵,实现植物自动浇水的功能。该系统可以检测土壤的湿度状况,根据设定的湿度阈值自动启动或停止灌溉,为植物提供适宜的生长环境。项目涉及硬件…

OpenStack API 来创建用户

OpenStack API 来创建用户。 代码详解 import requests import jsonrequests:用于发送 HTTP 请求的库。json:用于处理 JSON 数据格式的库。 controller_ip 10.104.43.10 url f"http://{controller_ip}:5000/v3/auth/tokens"controller_ip…

Ubuntu22.04 安装图形界面以及XRDP教程

一、准备环境 1.一台服务器安装系统ubuntu(这里大部分ubuntu系统可以同用) 2.安装的ubuntu系统未安装图形界面 二、操作步骤 1.远程ssh或者直接登录服务器命令行界面 ssh -p 远程端口 rootIP 2.更新系统软件包 sudo apt update # 更新本地的软件包…

C++:多态中的虚/纯虚函数,抽象类以及虚函数表

我们在平时,旅游或者是坐高铁或火车的时候。对学生票,军人票,普通票这些概念多少都有些许耳闻。而我们上篇文章也介绍过了继承与多继承。如果这些票我们都分别的去写一个类,当然很冗余,这里我们便可以去使用继承&#…

【易售校园二手平台】开源说明(包含项目介绍、界面展示与系列文章集合)

文章目录 仓库项目介绍技术架构界面登录界面首页闲置商品发布商品详情收藏页面消息页面私聊我的查看我发布的商品 可优化点开发讲解文章集合 仓库 🏠️ 项目仓库:易售校园二手平台gitee仓库 🌍️ 在线体验:易售校园二手平台&…

python怎么将字符串转换为数字

python如何将列表中的字符串转为数字?具体方法如下: 有一个数字字符的列表: numbers [1, 5, 10, 8] 想要把每个元素转换为数字: numbers [1, 5, 10, 8] 用一个循环来解决: new_numbers []; for n in numbers:new_n…

APP 后台广告位配置的关键要素与策略

在当今数字化营销的浪潮中,APP 作为重要的信息传播渠道,其后台广告位的配置显得尤为关键。这不仅影响着广告的展示效果,还直接关系到用户体验和平台收益。 首先,了解目标受众是配置广告位的基础。通过对 APP 用户的行为数据进行分…

创建MoveIt! Package

2.1 准备URDF package 首先我们要准备一个机械臂的urdf,如果你已有URDF,可以使用自己的urdf模型。若手头没有现成的URDF,可以从此处下载一个库卡LWR简化模型URDF,这是一个固定底座7自由度的机械臂。 从该连接处依次进入examples/s…

穴位大揭秘:使用「人体穴位图解」,轻松学会精准按摩技巧

软件介绍 人体穴位图解是一款免费无广提供人体穴位图解、人体经络病症及穴位图表的应用,采用目前流行的Flutter框架开发,遍布肺、肠、脾、胃、心、肝等部位。该应用所有资料均来自相关公共医学文献,具有一定的参考价值,通过图文介…

java-web-day14-项目属性配置和bean的管理

springboot支持的属性配置方式 1.配置文件配置: application.properties application.yml application.yaml 2.java属性配置 -D... 例如配置端口号: -Dserver port 10000 3.命令行参数 --.... 例如配置配置端口号 --server port 10000 三者的发挥作用优先级: 命令行参数>jav…

c++算法练习(3)石头剪刀布、输出亲朋字符串、配对碱基对、标准库的字符替换、密码翻译

#include <string>vector<string>results;results.push_bask(string1);for(const auto &result :result)//字符串可以用下表访问string myString;string.length()ss.replace(ss,find(A),1,T);char operator()(char ch) const class SomeClass {private:int mem…

SpringBoot二手车交易管理系统-计算机毕业设计源码02893

目 录 摘要 1 绪论 1.1 选题背景与意义 1.2开发现状 1.3论文结构与章节安排 2 二手车交易管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例…

Linux scp命令 | 菜鸟教程-从本地复制到远程/从远程复制到本地

目录 Linux scp命令 语法 实例 1、从本地复制到远程 2、从远程复制到本地 说明 文章来源&#xff1a;Linux scp命令 | 菜鸟教程 Linux scp命令 nux scp 命令用于 Linux 之间复制文件和目录。 scp 是 secure copy 的缩写, scp 是 linux 系统下基于 ssh 登陆进行安全的远…

linux node vue3 部署手册

第一步&#xff1a;在linux 系统中安装node 1、在网址&#xff1a;https://nodejs.org/dist/ 下载对应版本的安装包。 2、解压缩下载的压缩包到任意位置&#xff0c;推荐home下。 样例路径为&#xff1a;/home/syl/node-v20.17.0-linux-x64.tar.xz 样例&#xff1a; tar -xv…

nohup-tail

在 Linux 下&#xff0c;可以使用 wget 命令将文件下载到后台&#xff0c;以便在终端关闭或会话中断时&#xff0c;下载仍能继续。你可以使用以下命令&#xff1a; nohup wget http://ftp.genek.cn:8888/alxbbc_20220606/BSA_training.zip &解释 nohup&#xff1a;让命令…

Intel AMT技术在服务器硬件监控中的应用与解读

随着信息技术的飞速发展&#xff0c;服务器硬件的稳定性和可靠性成为了企业运维团队关注的重点。为了实时监控服务器的各项性能指标&#xff0c;及时发现并解决潜在问题&#xff0c;各种监控技术应运而生。其中&#xff0c;Intel AMT&#xff08;主动管理技术&#xff09;以其独…