Promise原理解析与实现

Promise原理解析与实现

知识要点

  • Promise 类
  • Promise 状态
  • promise.resolve 方法实现
  • promise.reject 方法实现
  • promise.then 方法实现
  • promise.catch 方法实现

学习目标

  • 了解 Promise 基本实现原理
  • 深入掌握 Promise 的使用细节
  • 了解 Promise 未来新标准新特性

介绍

PromiseJavaScript 异步编程的一种流行解决方案,掌握 Promise 的使用是我们不可或缺的一项基本技能。但是要想熟练掌握并深入的理解它,还是必须要知道它的实现原理的。这节课就是从具体使用角度出发,使用原生手写方式一步一步的带你实现 Promise 库,而且不仅仅只是包含了 Promise 目前通用的功能,还有 Promise 的一些新的特性和未来即将支持的特性的介绍与实现

Promise 类

Promise 的构造函数必须接收一个函数参数(也就是需要执行异步任务的函数),该函数将在传入以后立即调用,并传入 Promise 对象下的两个方法 resolvereject

Promise 状态

每一个 Promise 对象都存在以下三种状态:

  • PENDING : 进行中,Promise 对象的初始状态
  • FULFILLED : 已成功
  • REJECTED : 已失败

每一个 Promise 对象只能由 PENDING 状态变成 FULFILLEDREJECTED,且状态发生变化以后就能再改变了 ---- 记住这个特性

一个 Promise 对象状态的变化并不由 Promise 对象本身来决定,而应该是由我们传入的异步任务完成情况来决定的,Promise 提供了两个用来改变状态的方法

promise.#resolve 方法

Promise 对象的状态从 PENDING 变为 FULFILLED,并执行成功后的注册任务

注意:如果当前状态已经改变过了,则直接 return

promise.#reject 方法

Promise 对象的状态从 PENDING 变为 REJECTED,并执行失败后的注册任务

注意:如果当前状态已经改变过了,则直接 return

promise.then 方法

thenPromise 对象提供的一个方法,它接收两个函数作为参数,分别注册到 resolvereject 方法执行后的任务队列中,我们需要在 Promise 中维护两个队列

  • fulfilledQueues
  • rejectedQueues

添加任务

then 方法中接收到的两个函数分别添加到对应的任务队列中

执行任务

Promise.resolvePromise.reject 方法中调用执行对应的任务队列的所有注册函数

宏任务 & 微任务

在这里插入图片描述

在这里插入图片描述

  • 异步任务
    • 微任务:一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前。
    • 宏任务:宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合。

then 方法是一个微任务

  • setTimeout(fn, 0);
  • MutationObserver

结果传递

在调用 reslove 或者 reject 方法的时候,我们还可以通过传入一些值,在后续的 then 方法中,可以通过对应的函数接收到该结果

如果在一个 Promise 对象的状态改变后调用then 则会立即执行添加的对应函数,所以需要注意必须根据当前 Promise 的状态来做不同的处理

  • PENDING : 添加到对应的任务队列
  • FULFILLED / REJECTED : 不用添加到队列,而是立即执行任务

返回值

then 方法在执行最后必须返回一个新的 Promise 对象

重点(难点)

返回 Promise对象会立即调用并执行,如果这个时候,直接去执行该对象的 resolve 或者 reject 方法都会导致后续的 then 也立即被调用

我们需要对原 fulfilledHandlerrejectedHandler 进行包装,把它们和新 Promise 对象的 resolvereject 方法分别放置到新的函数中,并把这个新的函数添加到原有任务队列中调用

简而言之:把新返回的 Promise 对象的 resolverejectthen 中执行的 fulfilledHandlerrejectedHandler 添加到一个任务队列中执行,这样才能使用原有的 then 执行完成以后才执行新的 Promise 中的 then

上面是默认情况下的处理情况,其实 then 方法的处理更为复杂

当一个Promise完成(fulfilled)或者失败(rejected),返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回:

  • 如果then中的回调函数没有返回值,那么then返回的Promise将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined。
  • 如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 如果then中的回调函数返回一个已经是接受状态的Promise,那么then返回的Promise也会成为接受状态,并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  • 如果then中的回调函数返回一个已经是拒绝状态的Promise,那么then返回的Promise也会成为拒绝状态,并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。

promise.catch 方法

promise.finally 方法

ECMA2018 Added

Promise.resolve 方法

Promise.reject 方法

Promise.all 方法

Promise.race 方法

总结

  • Promise 类
  • Promise 状态
  • promise.resolve 方法实现
  • promise.reject 方法实现
  • promise.then 方法实现
  • promise.catch 方法实现

https://source.chromium.org/chromium/chromium

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌开心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值