一起来手写简易版promise

本文探讨了如何手写简易版的Promise,详细解释了Promise的核心逻辑,包括状态管理、异步处理、then的链式调用、catch方法、All方法等。通过理解并实践Promise的API,有助于提升对Promise及其工作原理的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信大家学了promise后,面试都会遇到手写promise的现象,我也尝试了通过自己的理解来简单的实现promise手写,发现只要将官方的promise整个API执行了解透彻,手写其实还是很好掌握的,一起来看看~

核心逻辑

首先我们需要知道promise的核心逻辑

01 Promise是一个类,在执行类的时候,需要传递一个执行器,只要new了,执行器就会执行

02 Promise中有三种状态,等待Pending,成功Fulfilled,失败Rejectd,一旦确定就不能再更改

03 resolve和reject函数都是用来更改状态的,resolve:fulfilled;reject:rejected

04 then内部做的事情就是判断状态,如果状态是成功的,调用成功的函数,如果状态是失败,则调用失败函数

05 then成功回调有一个参数,表示成功后的值;失败回调会有一个参数,表示失败的原因

//基础的promise手写实现
const PENDING = 'pengding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
    //构造一个执行器
    constructor (executor){
        executor(this.resolve,this.reject)
    }
    //promise的状态
    status = PENDING;
    //成功失败的值
    value = undefined
    reason = undefined
    //定义执行函数 
    resolve = value =>{
        //只有在等待着状态才可以更改状态值
        if(this.status !== PENDING) return;
        this.status = FULFILLED;
        this.value = value
    }
    reject = reson => {
        //只有在等待着状态才可以更改状态值
        if(this.status !== PENDING) return;
        this.status = REJECTED;
        this.reson = reson
    }
    then (successCallback,failCallback) {
        //判断状态然后再执行
        if (this.status === FULFILLED){
            successCallback(this.value)
        } else if(this.status === REJECTED) {
            failCallback(this.reson)
        }
    }
}
module.exports = MyPromise
异步处理

当reject中内容使用定时器时,并不影响主线程then的执行,那么需要将成功失败处理函数暂存起来,等到主线程执行结束处理返回执行宏任务时,直接使用缓存的处理函数执行

多个then的执行

就是将缓存处理函数的所有值都保存在一个数组中,当多个then执行的时候,就从数组中shift()弹出执行,直到数组长度为0

//成功失败的处理函数暂存
successCallback = []
failCallback = []
//定义执行函数 
resolve = value =>{
    //只有在等待着状态才可以更改状态值
    if(this.status !== PENDING) return;
    this.status = FULFILLED;
    this.value = value
    //如果缓存中存在函数,则执行
    //this.successCallback && this.successCallback(this.value)
    while(this.successCallback.length) this.successCallback.shift()(this.value)
}
reject = reason => {
    //只有在等待着状态才可以更改状态值
    if(this.status !== PENDING) return;
    this.status = REJECTED;
    this.reason = reason
    // this.failCallback && this.failCallback(this.reason)
    while(this.failCallback.length) this.failCallback.shift()(this.reason)
}
then的链式调用

01 首先必须返回一个promise对象后才能再次then调用

02 需要将第一次返回的结果作为第二次then调用的参数

03 将每次的执行结果保存在变量中,作为resolve执行函数的参数

04 如果返回的是一个普通值直接执行,如果是继续是一个promise对象,那么就需要对它的结果做判断再去执行

识别自返回

在原封装的promise函数中,不允许then回调执行后返回自己,所以我们需要单独添加一个判断条件,存在问题在于执行过程中无法直接拿到promise结果,就需要我们通过异步实现

 then (successCallback,failCallback) {
        successCallback = successCallback ? successCallback : this.value = this.value ;
        failCallback = failCallback ? failCallback : this.reason = this.reason ;
        let promise2 = new MyPromise((resolve,reject) => {
            //判断状态然后再执行
            if (this.status === FULFILLED){
                let x = successCallback(this.value)
                //通过异步实现识别promise对象自返回
                setTimeout(() => {
                    //处理返回结果,看是promise对象还是直接数值
                    resolvePromise(x,resolve,reject)
                })
            } else if(this.status === REJECTED) {
                failCallback(this.reason)
            } else {
                //走到了pending分支
                this.successCallback.push(successCallback)
                this.failCallback.push(failCallback)
            }
 })
function resolvePromise (x,resolve,reject) {
    //判断返回的是否是对象
    if( x instanceof MyPromise) {
        // x.then(value=>{resolve(value)},reason =>{reject(reason)})
        x.then(reject,resolve)
    } else {
        resolve(x)
    }
}
检错能力

通过在构造执行器的时候添加try,catch可以对成功和失败检错,我们封装一个检错的添加到所有的catch执行中去

01 执行器错误

02 执行函数错误

03 缓存执行函数时错误

catch方法

就是执行failcallback函数,对正确函数传参传入undefined,并不注册成功回调,而是注册失败回调

catch (failCallback) {
  return this.then(undefined,failCallback)
}
All方法

解决异步并发问题,实则就是有一个数组来存,如果是数值,直接存进去,如果是promise对象,那就需要单独执行完后,将结果放入

static all (array) {
    let reasult =[];
    let index = 0;
    return new MyPromise ((resolve,reject) => {
        function addData(key,value){
            reasult[key]=value
            index++
            if(index === array.length) {
                resolve(reasult)
            }
        }

        for(let i = 0;i<array.length;i++) {
            let current = array[i]
            if(current instanceof MyPromise) {
                //promise对象的处理
                current.then(value=>addData(i,value),reason=>reject(reason))
            } else {
                //对于普通值
                addData(i,array[i])
            }
        }
    })
}
resolve方法

返回结果是一个promise对象,如果是数值,需要作为参数返回一个promise对象,如果是promise对象,就直接返回结果

static resolve (value) {
    if (value instanceof MyPromise) return value
    return new MyPromise (resolve => resolve(value))
}
finally方法

无论是正确还是错误都会去执行结果,并且会等待延迟的执行之后再去调用

finally (callback) {
    return this.then (value => {
        return MyPromise.resolve(callback()).then(() => value)
    },
    reason => {
        return MyPromise.resolve(callback()).then(() => {throw reason})
    })
}

简易版的手写promise就到这里实现的差不多了,具体细节也没过多展示,下来也得多琢磨琢磨看,大家有问题可以一起谈论看看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值