面试题系列 手写Promise

目录

构建MyPromise基础类

实现Promise的then方法

MyPromise.resolve() 

MyPromise.reject() 

MyPromise.all()

MyPromise.race() 

MyPromise.any()

 MyPromise.allSettled()


构建MyPromise基础类

首先需要构建一个MyPromise类

class MyPromise {
    constructor(executor) {
        this.initBind()
        this.initValue()
        try  {
            executor(this.resolve, this.reject);
        } catch (e) {
            this.reject(e)
        }
    }
    initValue() {
        this.PromiseState = "pending"
        this.PromiseResult = null;
        this.onFulfilledCallbacks = []; // 保存成功的回调
        this.onRejectedCallbacks = []; // 保存失败的回调
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if(this.PromiseState !=="pending") return 
        this.PromiseResult = value;
        this.PromiseState = "fulfilled"
        while(this.onFulfilledCallbacks.length) {
            let resolveFun = this.onFulfilledCallbacks.shift();
            resolveFun(this.PromiseResult)
        }
    }
    reject(reason) {
        if(this.PromiseState !=="pending") return 
        this.PromiseResult = reason;
        this.PromiseState = "rejected"
        while(this.onRejectedCallbacks.length) {
            let rejectFun = this.onRejectedCallbacks.shift();
            rejectFun(this.PromiseResult)
        }
    }
}

实现Promise的then方法

这个方法接受两个函数类型的参数,分别是成功和失败的回调函数

MyPromise.prototype.then = function(onFulfilled, onRejected) {
    let state = this.PromiseState;
    // 首先校验这两个参数是不是一个函数
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val
    onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason }

    if(state === "fulfilled") {
      // 执行成功的回掉函数
      // onFulfilled(this.PromiseResult)
        resolvePromise(onFulfilled)
    } else if(state==="rejected")
      // onRejected(this.PromiseResult)
         resolvePromise(onRejected)
    } else if(state ==="pending") {
        console.warn("遇到了异步函数,此时的状态肯定是pending,那么就把这个异步处理函数放到成功或者失败回调函数中,等到reject()或者resolve()的时候,再去调用");
            // console.log(onFulfilled, onRejected);
            this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
            this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
        }
    })
    
}

因为then方法是支持链式调用的,所以then方法的返回值也需要是一个MyPromise实例对象,所以我们在上面基础上做一定的修改

MyPromise.prototype.then = function(onFulfilled, onRejected) {
    let state = this.PromiseState;
    // 首先校验这两个参数是不是一个函数
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val
    onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason }

    var thenPromise = new MyPromise((resolve, reject) => {
        const resolvePromise = cb => {
            setTimeout(() => {
                try {
                    const x = cb(this.PromiseResult)
                    if (x === thenPromise) {
                        // 不能返回自身哦
                        throw new Error('不能返回自身。。。')
                    }
                    if (x instanceof MyPromise) {
                        // 如果返回值是Promise
                        // 如果返回值是promise对象,返回值为成功,新promise就是成功
                        // 如果返回值是promise对象,返回值为失败,新promise就是失败
                        // 谁知道返回的promise是失败成功?只有then知道
                        x.then(resolve, reject)
                    } else {
                        // 非Promise就直接成功
                        resolve(x)
                    }
                } catch (err) {
                    // 处理报错
                    reject(err)
                    throw new Error(err)
                }
            })
        }
        if(state === "fulfilled") {
            // 执行成功的回掉函数
            // onFulfilled(this.PromiseResult)
            resolvePromise(onFulfilled)
        } else if(state==="rejected"){
            // onRejected(this.PromiseResult)
            resolvePromise(onRejected)
        } else if(state ==="pending") {
            console.warn("遇到了异步函数,此时的状态肯定是pending,那么就把这个异步处理函数放到成功或者失败回调函数中,等到reject()或者resolve()的时候,再去调用");
            // console.log(onFulfilled, onRejected);
            this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
            this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
        }
    })
    return thenPromise
}

MyPromise.resolve() 

快速创建一个成功的MyPromise对象

MyPromise.__proto__.resolve = function(value) {
    return new MyPromise((resolve, reject)=> {
        resolve(value)
    })
}

MyPromise.reject() 

快速创建一个失败的MyPromsie对象

MyPromise.__proto__.reject = function(reason) {
    return new MyPromise((resolve, reject)=> {
        reject(reason)
    })
}

MyPromise.all()

这个函数接受一个数组类型的参数,该数组的每一项都是一个Promise,或者非Promise的对象。

如果每一项的Promise的状态结果都是fulfilled,也就是成功的,那么这个函数的返回结果就是所有Promise的执行结果列表,状态为fulfilled,并且和传入数组顺序一致

如果有至少一个Promise的状态是rejected,那么这个函数的返回结束就是这个失败的Promise的结果,并且状态为rejected

MyPromise.__proto__.all = function(arr) {
    if(!Array.isArray(arr)) throw new Error("必须传入一个属猪")
    let resultArr = []
    let count = 0;
    return new MyPromise((resolve, reject)=>{
        for(let i = 0;i< arr.length; i++) {
            if(arr[i] instanceof MyPromise) {
                arr[i].then(res=>{
                    // 这里不能使用push添加,顺序会错乱
                    resultArr[i] = res;
                    count++;
                    if(count === arr.length) return resolve(resultArr)
                },err=>{
                    return reject(err)
                })
            } else {
                resultArr[i] = arr[i]
            }
        }
    })
}

MyPromise.race() 

接收一个数组类型的参数,返回结果是最先执行完的一个Promise,无论这个Promise事是成功还是失败的Promise 

MyPromise.__proto__.race = function(arr) {
    if(!Array.isArray(arr)) throw new Error("传入参数必须是一个数组")
    return new MyPromise((resolve, reject)=>{
        arr.forEach((promise)=>{
            if(promise instanceof MyPromise) {
                promise.then(res=>{
                    return resolve(res)
                }, err=>{
                    return reject(err)
                })
            } else {
                return resolve(promise)
            }
        })
    })
}

MyPromise.any()

该函数接受一个数组类型参数

1、如果参数中有一个Promise的状态是resolve,Promise.any() 返回一个resolve状态的Promise;
2、如果参数中全部的Promise的状态都变成了reject, Promise.any() 返回一个 reject 状态的Promise;

3、如果传递了一个空的数组,那么返回一个reject状态的Promise

MyPromise.__proto__.any = function(arr) {
    if(!Array.isArray(arr)) throw new Error("传入参数必须是一个数组")
    let count = 0;
    return new MyPromise((resolve, reject)=>{
        arr.forEach((promise, index)=>{
            if(promise instanceof MyPromise) {
                promise.then(res=>{
                    resolve(res)
                }, err=>{
                    count++;
                    if(count == arr.length) throw new Error("AggregateError: All MyPromises were rejected")
                })
            } else {
                resolve(promise)
            }
        })
    })
}

 MyPromise.allSettled()

该函数接收一个数组类型的参数

返回所有Promise的处理结果 如果不是一个Promise,那么返回成功的Promise

value是成功的Promise返回结果 reason是失败的返回结果

[

{state: "rejected", reason: "***"},

{state: "fulfilled", value: "***"},

]

MyPromise.__proto__.allSettled = function(arr) {
    if(!Array.isArray(arr)) throw new Error("传入参数必须是一个数组")
    return new MyPromise((resolve, reject)=>{
        let resultArr = []
        // let count = 0;
        for(let i = 0;i< arr.length;i++) {
            if(arr[i] instanceof MyPromise) {
                let obj = {status: "fulfilled"}
                arr[i].then(res=>{
                    obj.value = res;
                },err=>{
                    obj.status = "rejected"
                    obj.reason = err;
                })
                resultArr[i] = obj
            } else {
                resultArr[i] = {
                    status: "fulfilled",
                    value: arr[i]
                }
            }
        }
        resolve(resultArr)
    })
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值