手写Promise方法(实现Promise A+规范)

手写Promise


Promise 构造函数

我们先来写 Promise 的构造函数。需要处理的值如下:

  1. Promise 状态记录:this.state
  2. 记录成功或失败的值:this.valuethis.reason
  3. 收集解决和拒绝回调函数:this.resolveCallbacksthis.rejectCallbacks
  4. 执行首次传入的解决和拒绝回调函数:func(this.resolve, this.reject)
class myPromise {
   
    constructor(func) {
   
        this.state = 'pending' // Promise状态
        this.value = undefined // 成功的值
        this.reason = undefined // 失败的值
        this.resolveCallbacks = [] // 收集解决回调函数
        this.rejectCallbacks = [] // 收集拒绝回调函数
        try {
    // 对传入的函数进行try...catch...做容错处理
            func(this.resolve, this.reject) // 执行首次传入的两个回调函数
        } catch (e) {
   
            this.reject(e)
        }
    }
}

三个状态(pending、rejected和fulfilled)

pending:待定状态。待定Promise。只有在then方法执行后才会保持此状态。

fulfilled:解决状态。终止Promise。只有在resolve方法执行后才会由pending更改为此状态。

rejected:拒绝状态。终止Promise。只有在reject方法执行后才会由pending更改为此状态。

注意:其中只有pedding状态可以变更为rejectedfulfilledrejectedfulfilled不能更改其他任何状态。


三个方法(resolve、reject和then)

resolve方法实现要点

  1. 状态由pendingfulfilled。
  2. resolve方法传入的value参数赋值给this.value
  3. 按顺序执行resolveCallbacks里面所有解决回调函数
  4. 利用call方法将解决回调函数内部的this绑定为undefined

坑点 1resolve方法内部this指向会丢失,进而造成this.value丢失。

解决办法:我们将resolve方法定义为箭头函数。在构造函数执行后,箭头函数可以绑定实例对象的this指向。

// 2.1. Promise 状态
resolve = (value) => {
    // 在执行构造函数时内部的this通过箭头函数绑定实例对象
    if (this.state === 'pending') {
   
        this.state = 'fulfilled' // 第一点
        this.value = value // 第二点
        while (this.resolveCallbacks.length > 0) {
    // 第三点
            this.resolveCallbacks.shift().call(undefined) // 第四点
        }
    }
}

reject方法实现要点

  1. 状态由pendingrejected
  2. reject方法传入的reason参数赋值给this.reason
  3. 按顺序执行rejectCallbacks里面所有拒绝回调函数
  4. 利用call方法将拒绝回调函数内部的this绑定为undefined

坑点 1reject 方法内部this指向会丢失,进而造成this.reason丢失。

解决办法:我们将reject方法定义为箭头函数。在构造函数执行后,箭头函数可以绑定实例对象的this指向。

// 2.1. Promise 状态
reject = (reason) => {
    // 在执行构造函数时内部的this通过箭头函数绑定实例对象
    if (this.state === 'pending') {
   
        this.state = 'rejected' // 第一点
        this.reason = reason // 第二点
        while (this.rejectCallbacks.length > 0) {
     // 第三点
            this.rejectCallbacks.shift().call(undefined) // 第四点
        }
    }
}

then方法实现要点

  1. 判断then方法的两个参数onRejectedonFulfilled是否为function

    1.1 onRejectedonFulfilled都是function,继续执行下一步。

    1.2 onRejected不是function,将onRejected赋值为箭头函数,参数为reason执行throw reason

    1.3 onFulfilled不是function,将onFulfilled赋值为箭头函数,参数为value执行return value

  2. 当前Promise状态为rejected

    2.1 onRejected方法传入this.reason参数,异步执行。

    2.2 对执行的onRejected方法做容错处理,catch错误作为reject方法参数执行。

  3. 当前Promise状态为fulfilled

    3.1 onFulfilled方法传入this.value参数,异步执行。

    3.2 对执行的onFulfilled方法做容错处理,catch错误作为reject方法参数执行。

  4. 当前Promise状态为pending

    4.1 收集onFulfilledonRejected两个回调函数分别pushresolveCallbacksrejectCallbacks

    4.2 收集的回调函数同样如上所述,先做异步执行再做容错处理

  5. 返回一个 Promise 实例对象。

// 2.2. then 方法
then(onFulfilled, onRejected) {
   
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value // 第一点 
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
    throw reason } // 第一点 
    const p2 = new myPromise((resolve, reject) => {
   
        if (this.state === 'rejected') {
    // 第二点
            queueMicrotask(() => {
   
                try {
   
                    onRejected(this.reason)
                } catch (e) {
   
                    reject
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中提到了在回调函数中返回一个pending状态的promise对象的方法,这是因为在promise链中,执行then方法的成功或失败回调取决于上一个promise的状态。如果中间返回一个初始状态的promise对象,then方法无法确定执行哪个回调,后续的then方法也不会执行,导致promise链中断。 引用\[2\]中提到了手写Promise方法。为了实现链式调用,我们需要在第一个then方法中返回一个新的promise对象。根据官方规定,我们可以在then方法中创建一个新的promise对象,并将其命名为promise2。然后,我们可以将promise2返回的值传递给下一个then方法。如果返回的是一个普通值,则将该值传递给下一个then方法。 引用\[3\]中给出了一个基本的Promise实现的示例代码。首先,我们使用class关键字声明一个Promise类,并在构造函数中传入一个参数(executor函数)。executor函数有两个参数,resolve和reject,分别表示成功和失败。在executor函数中,我们可以执行异步操作,并在适当的时候调用resolve或reject来改变Promise的状态。根据官方规定,Promise存在三个状态:pending(等待态)、fulfilled(成功态)和rejected(失败态)。成功时,Promise的状态不可再次改变,并且需要有一个不可改变的值。失败时,Promise的状态也不可再次改变,并且需要有一个不可改变的原因。如果executor函数报错,直接执行reject()。 综上所述,手写Promise实现需要注意返回一个新的promise对象,并在适当的时候调用resolve或reject来改变Promise的状态。 #### 引用[.reference_title] - *1* *2* *3* [Promise学习笔记(尚硅谷)](https://blog.csdn.net/Ch_ensf/article/details/124699879)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值