【手写 Promise 源码】第一篇 - Promise 简介

news2024/12/30 3:07:40

一,前言

上一篇,完成了 Promise 源码学习的目录;

本篇,主要对 Promise 进行简单的概括介绍;


二,Promise 简介

  • Promise 是一个类或构造函数,是 JS 原生提供的,通过实例化 Promise 完成预期的异步任务处理;
  • Promise 是一个能够获取异步操作消息的对象;译为承诺,表示会在一段时间后返回处理结果;
  • Promise 是一种异步编程的解决方案,被 ES6 列为正式规范,提供了原生 Promise 对象;
  • Promise 能够接收一个异步请求,在提供的 then/catch 方法中拿到异步请求的处理结果;
  • Promise 支持链式调用,通过链式调用的方式能够将异步请求的结果以同步的方式进行处理;

三,Promise 基本使用

使用 Promise 对异步操作进行包装:

// 创建
var promise = new Promise((resolve, reject)=>{
  setTimeout(()=>{
    if("异步请求成功"){
      resolve('ok');
    } else {
      reject('error')
    }
  }, 2000);
});

// 使用
promise.then(data=>{
  console.log(data);
}).catch(error=>{
  console.log(error);
});

从示例中能够看出:

  • Promise 的参数是一个回调函数,其中包含了两个参数:resolve 和 reject;
  • 当异步操作成功时,通过调用 resolve 返回异步操作的成功结果;
  • 当异步操作失败时,通过调用 reject 返回异步操作的失败结果;
  • 异步操作成功时,进入 then 处理后续操作;
  • 异步操作失败时,进入 catch 处理后续操作;(当前示例是这样的,当then函数的第二个回调定义时,也可以捕捉失败操作,这个机制后面会详细解释)

但实际上,除以上示例体现出来的部分,Promise 还具有更多特性,理解并掌握这些特性是用好 Promise 的基础;


四,Promise 和 callback 对比

callback 方式处理异步操作:

function async(callback){
    setTimeout(function(){
        callback("异步操作完成");
    }, 1000);
}

async(function(data){
    console.log(data);
});

Promise 和 callback 的本质区别,就是控制权反转

  • 在 callback 模式下,回调函数的执行控制权在封装层:

    • 业务层将回调函数定义传递给封装层
    • 封装层在任务结束时执行了回调函数;
    • 业务层并没有调用回调函数,甚至连调用的代码都看不到;
  • 在 Promise 模式下,回调函数的执行控制权在业务层:

    • 业务层并没有把回调函数直接传递给封装层(Promise 对象内部);
    • 封装层在任务结束时,并不知道要执行的回调,只能通过 resolve 或 reject 通知到业务层,由业务层在 then() 或 reject() 中控制回调执行;
    • 业务层不仅能看到回调函数的调用代码,还能对其进行修改;

五,Promise 的作用

Promise 可以说(主要)是为了解决程序异步处理而生的;

  • Promise 不仅解决了异步回调的多层嵌套,即“回调地狱”问题;
  • 更重要的,Promise 提供了更完整、更强大的异步解决方案;通过 Promise 构造函数上提供的方法,实现对 Promise 批量操作的支持,如:all、race、any、allSettled 等;

六,Promise 的重要性

目前,Promise 在前端领域的应用中,几乎是无处不在的,已经成为了前端开发中最重要的技能之一;

Promise 也是前端面试的高频考察点:考察方式多样化,考察内容可深可浅;同时,也能够关联出很多实际应用场景;因此,熟练地掌握 promise 是每个前端开发的必备能力;


七,Promise 的兼容性

1,兼容性介绍

Promise 属于 ES6 规范内容,浏览器支持情况可查看 Can I use 或 MDN:

Can I use.png

MDN.png

  • Chrome 浏览器 - 支持
  • 360 浏览器 - 兼容模式下支持
  • IE 内核浏览器 - 不支持

2,解决方案

  • bluebird.js
    在项目中使用 Promsie 对象,可以使用第三方插件 bluebird.js;

bluebird 对 ES6 原生 Promise 进行封装,解决了浏览器兼容性问题;

  • es6-promise
    使用 es6-promise 也可以解决 IE 下不支持 Promise 的问题;

八,Promise 使用场景

JS 的异步处理可以说是无处不在的,比如:nodejs 和小程序所提供的 API 都是基于回调的;

而这也就导致了开发中时常出现“回调地狱”的坏味道(团队 CodeReview 关注点):

const fs = require('fs');

fs.readFile('./a.txt','utf8',(err,data)=>{
  if(err) return err
  console.log(data)
  fs.readFile('./b.txt','utf8',(err,data)=>{
    if(err) return err
    console.log(data)
    fs.readFile('./c.txt','utf8',(err,data)=>{
      if(err) return err
      console.log(data)
      fs.readFile('./d.txt','utf8',(err,data)=>{
        if(err) return err
        console.log(data)
        // ...回调地狱
      })
    })
  })
})

为了解决类似这种异步操作带来的问题,使代码编写更加优雅且更具可读性,Promise 作为前端异步编程的解决方案诞生了;

上边的代码使用 Promise 进行包装处理,如下:

const fs = require('fs');

// 使用 Promise 封装处理 fs.readFile
function readFile(filePath, encoding) {
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, encoding, (err, data) => {
      if (err) return reject(err) //失败
      resolve(data) // 成功
    })
  });
}

// 使用方式
readFile('./a.txt','utf8').then((data) => {
  console.log(data)
  return readFile('./b.txt','utf8')
}).then((data) => {
  console.log(data)
  return readFile('./c.txt','utf8')
}).then((data) => {
  console.log(data)
  return readFile('./d.txt','utf8')
}).then((data) => {
  console.log(data)
})

这种将异步回调包装成为 Promise 的处理方式也叫 Promisify,常用于 nodejs、小程序场景,使异步代码更简洁;

  • 备注:
    使用类库时仔细查看官方说明,目前很多类库都支持返回 Promise 实例,应尽量避免在外部进行重复包装;部分类库既支持 callback 也支持 Promise 形式;

九,Promise 优缺点

  • 优点

    • 优化异步代码,解决“回调地狱”问题,增强代码的可读性、可维护性;
    • Promise 对象提供统一的接口,使得控制异步操作更加容易;
    • 通过 catch 方法对异常进行统一的捕获处理;
  • 缺点

    • 无法取消 Promise,一旦创建它就会立即执行,无法中途取消;
    • 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部;
    • 当处于 Pending 状态时,是无法得知目前进展到哪一个阶段(刚刚开始还是即将完成);

十,结尾

本篇,对 Promise 进行了简单介绍,主要涉及以下几个点:

  • Promise 简介和基本使用;
  • Promise 和 callback 对比;
  • Promise 的重要性和作用;
  • Promise 使用场景:Promisify 封装;
  • Promise 的优缺点、兼容性;

备注:本篇的定位仅仅是简单的认识和了解 Promise,并未涉及深入的介绍和分析,比如:Promise 的状态、执行顺序、链式调用、api 使用、异常处理等;

下一篇,将结合示例对 Promise 进行相关功能介绍与特性分析;


维护日志

  • 20211019
    • 更新部分示例代码,更符合相关知识点;
    • 添加 promise 兼容性部分;
    • 更新结尾部分、文章摘要;
  • 20211024
    • 扩充部分内容;
  • 20211025
    • 重新梳理大纲,调整一二级标题、扩充相关内容;
    • 修改文章标题、摘要;

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

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

相关文章

【Java】还不懂this关键字?一分钟彻底弄懂this关键字

博主简介:努力学习的预备程序媛一枚~博主主页: 是瑶瑶子啦所属专栏: Java岛冒险记【从小白到大佬之路】 前言 问题:为什么会存在this? 在上一篇【JavaSE】一文看懂构造器/构造方法(Cunstructor)中,我们已…

更方便Spring存储和读取对象,五大类注解、@Bean、@Autowired、@Resource

上一篇博客我们介绍了如何使用xml来引入bean对象,当项目多的时候,显然那样是比较麻烦的。现在我们只需要 个注解就可以替代了。注意:注解和xml可以同时使用准备工作:配置扫描路径我们需要配置 下存储对象的扫描包路径,只有被配置的…

利用Windows系统服务进行权限提升

提权是后渗透重要的一环节,如果当前获取的用户权限比较低,那么我们将无法访问受保护的系统资源或执行系统管理操作,影响后续的攻击过程。这要求我们通过各种手段将当前用户的权限进行提升,以满足后续攻击的要求。利用系统服务提权…

VUE2--22.11.23

VUE2一、Vue.js devtools二、Vue简介1、什么是Vue2、Vue的特性1.数据驱动视图2.双向数据绑定3.MVVM三、Vue的基本使用1、基本使用步骤四、Vue的指令与过滤器1、什么是指令2、内容渲染指令1.v-text2.{{}}3.v-html3、属性绑定指令4、事件绑定指令5、双向绑定指令6、条件渲染指令7…

【Linux】动静态库、文件的三个时间

1.文件的三个时间Access: 访问时间,访问的频率很高,所以较新的Linux都是按一定的时间间隔刷新Modify: 修改文件内容时间Change:修改文件属性时间,修改文件内容也会修改文件属性makefile自动编译判断文件是否为最新:就是按可执行程…

运动基元(一):Dubin‘s曲线【part3】

3.5 RLR RLR的第一段圆弧的曲率 k 1 = − k m a x < 0 → s i g n ( k 1 ) = − 1 k_1=-k_{max}<0\rightarrow si

Springboot图书馆图书借阅管理系统x1x74

目 录 1 概述 1 1.1课题背景及意义 1 1.2 国内外研究现状 1 1.3 本课题主要工作 2 2 系统开发环境 3 2.1 java简介 3 2.2 Mysql数据库 3 2.3 B/S结构 4 2.4 JSP技术介绍 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2操作…

机器学习sklearn笔记:LDA(线性判别分析)

1 介绍 1.有监督的降维2.投影后类内方差最小&#xff0c;类间方差最大2 推导 我们记最佳的投影向量为w&#xff0c;那么一个样例x到方向向量w上的投影可以表示为&#xff1a; 给定数据集令分别表示第i类的样本个数、样本集合、均值向量和协方差矩阵——>在投影上的均值是 —…

kafka初识

安装kafka 下载 下载window的kafka地址 window的kafka只是为了方便学习 安装地址&#xff1a;kafka.apache.org/ 安装 解压zip为文件夹 启动kafka kafka服务器的功能相当于RocketMQ中的broker&#xff0c;kafka运行还需要一个类似于命名服务器的服务。在kafka安装目录中自…

Windows10添加WebDav地址时报错“输入的文件夹无效,请选择另一个”

一、问题描述在使用Windows10添加WebDav网络地址时&#xff0c;报错“输入的文件夹无效&#xff0c;请选择另一个”&#xff0c;如下图所示&#xff1a;二、问题分析这是由于Windows10的WebDav默认只支持https协议&#xff0c;没有支持http协议导致的。三、解决办法3.1、修改注…

计算机科学领域中里程牌式的算法

计算机科学中伟大的算法前言搜索引擎的索引PageRank公钥加密 --- 用明信片传输秘密纠错码数据压缩无损压缩有损压缩数据库 --- 追求一致性的历程事务和待办事项&#xff08;预写日志记录&#xff09;数字签名用挂锁签名用指数挂锁签名RSA的安全性前言 我肯定不是一位天文学专家…

redis 消息队列方案

redis 消息队列方案 观察角度&#xff1a;消息有序&#xff0c;重复消息处理&#xff0c;消息可靠性保证 pub/sub 发布订阅机制 list集合 消息有序&#xff1a;lpush和rpop可以保证消息顺序的被消费 重复消息处理&#xff1a;list没有为消息提供唯一标识&#xff0c;需要生产者…

利用matlab求解非线性目标函数

文章目录函数介绍设置函数参数步骤结果分析函数介绍 使用fmincon函数来进行求解&#xff0c;格式为 [x,y] fmincon(f,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)其中&#xff0c;f表示所求的目标函数&#xff0c;x0表示初始值&#xff0c;A,b,Aeq,beq表示线性的约束&#xff0c…

SpringBoot06:整合JDBC、Druid、MyBatis

整合JDBC 1、创建一个新的工程&#xff0c;勾选JDBC API和MySQL Driver 2、导入web启动器 3、编写yaml配置文件&#xff0c;连接数据库 spring:datasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/mybatis?useUnicodetrue&characterEncodingut…

力扣 2299. 强密码检验器 II

题目 如果一个密码满足以下所有条件&#xff0c;我们称它是一个 强 密码&#xff1a; 它有至少 8 个字符。 至少包含 一个小写英文 字母。 至少包含 一个大写英文 字母。 至少包含 一个数字 。 至少包含 一个特殊字符 。特殊字符为&#xff1a;“!#$%^&*()-” 中的一个。…

面向对象编程范式

目录 1.概述 1.1.面向对象编程的核心诉求 1.2.面向对象的世界观 2.类和对象 3.如何寻找类和对象 3.1.概述 3.2.示例 4.如何表示类 4.1.什么是UML 4.1.关系 4.2.权限 4.3.依赖 4.4.泛化&#xff08;继承&#xff09; 4.5.实现 4.6.关联 4.7.聚合 4.8.组合 1.概…

自定义类型之枚举和联合

该文章将详细介绍除结构体外的另外两种自定义类型--------枚举类型与联合类型。1.枚举1.1枚举类型的定义1.2枚举的优点1.3枚举的使用2.联合&#xff08;共用体&#xff09;2.1联合类型的定义2.2联合的特点2.3联合大小的计算1.枚举 枚举顾名思义就是------一一列举。 把所有可能…

ADAS HiL系统测试方案

1、什么是ADAS ADAS&#xff08;Advanced Driving Assistance System&#xff09;也就是高级驾驶辅助系统&#xff0c;是无人驾驶的过渡。 ADAS利用安装在车上的各式各样传感器&#xff08;毫米波雷达、激光雷达、单\双目摄像头以及卫星导航&#xff09;&#xff0c;在汽车行驶…

[前端笔记——CSS] 12.处理不同方向文本

[前端笔记——CSS] 12.盒模型背景与边框1.书写模式2.书写模式、块级布局和内敛布局3.逻辑属性和逻辑值1.书写模式 CSS 中的书写模式是指文本的排列方向是横向还是纵向的。writing-mode 属性使我们从一种模式切换到另一种模式。例如&#xff0c;我们使用writing-mode: vertical…

stack、queue、priority_queue

容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff0c;该种模式是将一个类的接口转换成客户希望的另外一个接口。 其中stack和queue都是容器适配器&#xff0c;其中stack可以封装vector、list以及我们…