【手写promise】终于不用担心我不会手写promise了

·  阅读 1247
【手写promise】终于不用担心我不会手写promise了

promise的特点,参考阮一峰ES6

  • Promise是一个构造函数,构造函数接收一个函数类型的参数
  • promise最后只能有一种状态,并且状态不能改变
  • promise构造函数的原型链上存在then catch方法,then/catch方法也返回promise
  • promise支持异步执行
  • promise支持链式调用
  • promise.all
  • promise.race

废话不多说,那我们下面就开始“搞事情”吧!

实现promise的第一步:做一些准备工作

  1. 我需要一个构造函数

Promise本身就是一个构造函数。

function MyPromise() {

}
MyPromise.prototype.then = function () { }
MyPromise.prototype.catch = function () { }
MyPromise.prototype.all = function () { }
MyPromise.prototype.race= function () { }
复制代码
  1. 准备一些“状态机”变量

promise有三种状态,一个promise必然会处在三个状态中的某一个状态里面

  • 待定(pending) : 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled) : 意味着操作成功完成。
  • 已拒绝(rejected) : 意味着操作失败。

下面第一个status变量来存储当前状态,定义success来表示成功状态下的值,error来表失败状态下的值。

function MyPromise() {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;

}
MyPromise.prototype.then = function () { }
复制代码

实现Promise的第二步:实现then函数。

这一步Promise的函数类型的参数可以起作用了,回调函数可以接收两个参数(resolve,reject),最后执行回调函数,在then函数中可以接收此时Promise的值

1. 将promise的值传给then函数

function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;
    function resolve(val) {
        that.status = 'fufilled';
        that.success = val;//保存当前成功的返回值
    }
    function reject(val) {
        that.status = 'rejected'
        that.error = val;
    }
    executor(resolve, reject);

}
复制代码

2. 让then函数来接收Promise执行后返回的值

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    handleFulfilled(this.success);//成功的值
    handleRejected(this.error);//失败的值
}
复制代码

3. new一个实例看看

  • 用我们写的MyPromise来new一个实例

function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;
    function resolve(val) {
        that.status = 'fufilled';
        that.success = val;//保存当前成功的返回值
    }
    function reject(val) {
        that.status = 'rejected'
        that.error = val;
    }
    executor(resolve, reject);

}

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    handleFulfilled(this.success);//成功的值
    handleRejected(this.error);//失败的值
}
let mypromise = new MyPromise((resolve, reject) => {
    resolve('success');
    reject('reject');
})
mypromise.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
复制代码

输出的结果如下:

image.png

不对丫,不是说promise只能有一种状态的都嘛,那现在?

  • 看看Promise new出来的实例呢
let promise = new Promise((resolve, reject) => {
    resolve('success');
    reject('reject');
})
promise.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
复制代码

输出的结果如下:

image.png

诺,只输出了一种状态,再将我们的promise改吧改吧。

实现promise的第三步:让promise的状态只能有一个

我们只允许promise的状态从pending=>fufilled或者pending=>rejected,所以,在then函数中加了一次判断。

function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;
    function resolve(val) {
        if (that.status == "pending") {
            that.status = 'fufilled';
            that.success = val;//保存当前成功的返回值
        }

    }
    function reject(val) {
        if (that.status == "pending") {
            that.status = 'rejected'
            that.error = val;
        }
    }
    executor(resolve, reject);
}

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    let that = this;
    debugger
    //根据当前的状态,执行对应的状态处理函数
    if (that.status == 'fufilled') { 
        handleFulfilled(this.success);//成功的值
    }
    if (that.status == 'rejected') {
        handleRejected(this.error);//失败的值
    }

}
let mypromise = new MyPromise((resolve, reject) => {
    resolve("success");
    reject("error");
})
mypromise.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})

复制代码

再试试呢?只输出了一个值,现在状态总算是对了。

image.png

实现promise的第四步:异步呀异步,关键是要让promise函数执行异步丫

看看Promise函数是怎么处理的

这里我们用setTimeout函数来模拟异步

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("success");
        reject("error");
    }, 2000)

})
promise.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
复制代码

运行上面的代码,2s后会输出一个状态:success,这里先执行的resolve,执行之后状态不会改变。

试试我们的mypromise呢

function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;
    function resolve(val) {
        if (that.status == "pending") {
            that.status = 'fufilled';
            that.success = val;//保存当前成功的返回值
        }

    }
    function reject(val) {
        if (that.status == "pending") {
            that.status = 'rejected'
            that.error = val;
        }
    }
    executor(resolve, reject);
}

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    let that = this;
    if (that.status == 'fufilled') {
        handleFulfilled(this.success);//成功的值
    }
    if (that.status == 'rejected') {
        handleRejected(this.error);//失败的值
    }

}
let mypromise = new MyPromise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        resolve("success");
        reject("error");
    }, 2000)

})
mypromise.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
复制代码

好了,执行!!我等鸭等等了2s,哎不止2s,依然啥都没有输出。 我们来分析一哈,这个是爪子回事嘛

  • 第一步:执行new Promise里面的内容
  • 第二步:执行到executor(resolve, reject);
  • 第三步:遇到setTimeout标记为宏2任务,等待。
  • 第四步:执行then函数 ,但是status状态为pending,handleFulfilled, handleRejected此时没有被执行
  • 第四步:2s到了,开始执行Promise里面的resolve函数,resolve函数执行完了,给status/success/error赋值

关键的问题是:遇到异步问题的时候,我们不想让then里面的handleFulfilled, handleRejected函数那么快执行。 使用两个变量,当执行到then的时候,如果状态为pending将handleFulfilled, handleRejected参数存下来,等到2s之后调用resolve函数的时候,再调用handleFulfilled处理接收值。

  function MyPromise(executor) {
            this.status = 'pending';//初始状态
            this.success = undefined;
            this.error = undefined;
            let that = this;

            that.onfufilledCallback = null;
            that.onrejectedCallback = null;

            function resolve(val) {
                debugger
                if (that.status == "pending") {
                    that.status = 'fufilled';
                    that.success = val;//保存当前成功的返回值
                    that.onfufilledCallback(that.success);
                } 

            }
            function reject(val) {
                if (that.status == "pending") {
                    that.status = 'rejected'
                    that.error = val;
                    that.onrejectedCallback(that.error);//同步执行的时候缓存
                }
            }
            executor(resolve, reject);
        }

        MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
            let that = this;
            if (that.status == 'fufilled') {
                handleFulfilled(this.success);//成功的值
            }
            if (that.status == 'rejected') {
                handleRejected(this.error);//失败的值
            }
            if (that.status == 'pending') {
                that.onfufilledCallback = handleFulfilled//将处理函数存下来
                that.onrejectedCallback = handleRejected//将处理函数存下来
            }
        }
        let mypromise = new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
                reject("error");
            }, 2000)

        })
        mypromise.then((res) => {
            console.log(res)
        }, (err) => {
            console.log(err)
        })
复制代码

2s后成功输出:success 梳理一下执行过程

  • 第一步执行new Promise里面的内容
  • 第二步执行executor(resolve, reject),执行executor的时候遇到setTimeout将setTimeout标记为宏任务,入栈;
  • 执行then then里面的函数为status为pending 将handleFulfilled函数缓存
  • 执行setTimeout里面的resolve 此时的状态是pending
  • 执行then中的缓存函数--->that.onfufilledCallback()

实现promise的第五步:说好的promise支持经典的链式调用呢

看看Promise

第二个then函数接收到了第一个then函数return出去的值

  • 执行resolve
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("success");
    }, 2000)

})
promise.then((res) => {
    console.log(res)
    return 1
}, (err) => {
    console.log(err)
}).then(res => {
    console.log(res)
})
复制代码

image.png

  • 执行reject

image.png 所以不管上一个then走的是resolve还是reject状态,第二个then函数都可以接收到第一个then的返回值 用我们第四步的MyPromise去执行上面相同的代码呢

let mypromise = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
        reject("error");
    }, 2000)

})
mypromise.then((res) => {
    console.log(res)
    return 1
}, (err) => {
    console.log(err)
}).then(res => {
    console.log(res)
})
复制代码

好家伙,直接报错,嗯,不用想肯定也会报错,我们的then函数返回的也根本不是promise哇

image.png

让我们的MyPromise也支持链式调用 怎么办?那还不简单,让我们的then函数返回一个promise不就行了?

  • 将我们的MyPromise.prototype.then函数直接返回一个promise
function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;

    that.onfufilledCallback = [];
    that.onrejectedCallback = [];

    function resolve(val) {
        if (that.status == "pending") {
            that.status = 'fufilled';
            that.success = val;//保存当前成功的返回值
            that.onfufilledCallback(that.success);
        }

    }
    function reject(val) {
        if (that.status == "pending") {
            that.status = 'rejected'
            that.error = val;
            that.onrejectedCallback(that.error);//同步执行的时候缓存
        }
    }
    executor(resolve, reject);
}

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    let that = this;
    let mypromise2 = new MyPromise((resolve, reject) => {

        if (that.status == 'fufilled') {
            try {
                let res = handleFulfilled(this.success);//成功的值
                resolve(res);
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == 'rejected') {
            try {
                let err = handleRejected(this.error);//失败的值
                resolve(err);
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == 'pending') {
            that.onfufilledCallback = handleFulfilled//将处理函数存下来
            that.onrejectedCallback = handleRejected//将处理函数存下来
        }
    })
    return mypromise2
}
let mypromise = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
        reject("error");
    }, 2000)

})
mypromise.then((res) => {
    console.log(res)
    return 1
}, (err) => {
    console.log(err)
}).then(res => {
    console.log(res)
})

复制代码

执行输出:现在是不报错了,但是第二个then函数根本也没有执行

image.png

  • 按照第二步的思路,我们有一个then函数就会缓存这个then函数的handleFulfilled,然后等2s之后执行这个handleFulfilled,那么有多个then的时候是不是也需要缓存多个then的handleFulfilled,然后等2s之后将所有的依次执行
function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;

    that.onfufilledCallback = [];
    that.onrejectedCallback = [];

    function resolve(val) {
        if (that.status == "pending") {
            that.status = 'fufilled';
            that.success = val;//保存当前成功的返回值
            that.onfufilledCallback.forEach(resolvefn => {
                resolvefn(that.success);
            });
        }

    }
    function reject(val) {
        if (that.status == "pending") {
            that.status = 'rejected'
            that.error = val;
            that.onrejectedCallback.forEach(rejectfn => {
                rejectfn(that.error);
            });//同步执行的时候缓存
        }
    }
    executor(resolve, reject);
}

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    let that = this;
    let mypromise2 = new MyPromise((resolve, reject) => {
        debugger
        if (that.status == 'fufilled') {
            try {
                let res = handleFulfilled(this.success);//成功的值
                resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == 'rejected') {
            try {
                let err = handleRejected(this.error);//失败的值
                resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == 'pending') {

            //当函数调用的时候,去执行数组里面的函数
            that.onfufilledCallback.push(() => {
                try {
                    let res = handleFulfilled(this.success)
                    resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                } catch (e) {
                    reject(e)
                }
            });//这里的onfufulled就相当于then里面的第一个参数回调
            that.onrejectedCallback.push(() => {
                try {
                    let res = handleRejected(this.error);
                    resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                } catch (e) {
                    reject(e)
                }

            });
        }
    })
    return mypromise2
}
let mypromise = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
        reject("error");
    }, 2000)

})
mypromise.then((res) => {
    console.log(res)
    return 1
}, (err) => {
    console.log(err)
}).then(res => {
    console.log(res)
})

复制代码

看看输出:

image.png 多调用几次then呢

image.png

发生了什么,怎么一下子就对了,那我们来分析一下上面的代码都干了啥吧

  • 第一步:依然是执行new Promise中的同步代码,我们加了两个数组 that.onfufilledCallback = [];that.onrejectedCallback = [];来缓存then函数的handleFulfilled方法, handleRejected方法
  • 第二步:执行 executor(resolve, reject);的时候遇到setTimeout,那就先等等再来执行setTimeout里面的东西吧
  • 第三步:执行第一个then吧
  • 第四步:在then函数里面有new MyPromise执行吧
  • 第五步:执行then函数中的executor(resolve, reject),同步执行当前的状态是pending,并且将当前handleFulfilled, handleRejected缓存了下来
  • 第六步:执行第二个then函数,操作过程同上一个then,依次将第二个then的handleFulfilled缓存下来
  • 第七步:第三个then执行,缓存
  • 第八步:终于轮到setTimeout函数执行了,执行resolve然后将上面缓存的三个then函数里面的全部执行

总结这一步的关键点

  • 定义缓存数组
  • 执行resolve的时候将缓存数组里的函数依次执行

实现promise的第六步,那么catch函数也得会嘛

与then函数不同的是catch函数只接受一个参数,执行catch函数相当于走then函数的第二个参数函数

MyPromise.prototype.catch = function (callback) {
    return this.then(function () { }, callback)
}
复制代码


let mypromise = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        reject("error");
    }, 2000)

})
mypromise.catch(err => {
    console.log(err)
})
复制代码

输出:error

实现promise的第七步:也得让我们的MyPromise支持promise.all嘛

先看看Promise.all的用法吧

  • 我传入一个普通的数组:输出[1,2]
Promise.all([1, 2]).then(res => {
    console.log(res)
})
复制代码
  • 传入异步函数数组:输出:[promise1,promise2]
let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise1');
    }, 2000)
})

let promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise2');
    }, 2000)
})
Promise.all([promise1, promise2]).then(res => {
    console.log(res)
})
复制代码

如果传入的是普通数组,传入啥就返回啥,如果是promise数组,执行每个promise,将结果返回,当我们都执行完数组里面的函数的时候,需要resolve

MyPromise.prototype.all = function (values) {
    return new Promise(function (resolve, reject) {
        let num = 0;
        let arr = [];

        for (let i = 0; i < values.length; i++) {
            let current = values[i];
            if (current.then && typeof current.then == "function") {
                //此时是promise对象
                current.then.call(current, function (val) { //此时是执行完的结果
                    arr[i] = val
                    if (++num == values.length) {
                        resolve(arr)
                    }
                }, reject)
            } else {
                //说明是具体的值
                arr[i] = current
                if (++num == values.length) {
                    resolve(arr)
                }
            }
        }
    })
}
复制代码

实现promise的第八步,顺便把race也实现了吧

MyPromise.prototype.race = function (values) {
    return new Promise(function (resolve, reject) {
        try {
            let num = 0;
            let arr = [];
            let current
            for (let i = 0; i < values.length; i++) {
                current = values[i]
                if (current.then && typeof current.then == "function") {
                    current.then(resolve, reject)
                } else {
                    resolve(current)
                }
            }

        } catch (e) {
            reject(e)
        }

    })
}
复制代码

总结一下吧

  • 第一步的时候做了一些准备工作
  • 第二步实现了then函数,利用回调函数,分别处理了成功的值和失败的值
  • 第三步:promise的状态只能有一个,用了status来判断当前应该走哪一个处理函数
  • 第四步:让promise支持异步调用,关键点就是缓存then函数,等同步函数执行完之后,再执行then里面的函数。
  • 第五步:链式调用,链式调用关键一步是让then函数也返回一个promise,同时要要缓存多个then函数的处理函数,等到同步执行完之后,依次执行then函数里面的处理函数。
  • 第六步里面的catch,和then函数的区别:catch相当于then函数中走的第二个reject回调
  • 第七步:promise all :分为promise数组和普通数组,普通数组直接输出,promise数组依次执行,当数组里面的promise都执行完之后,输出执行后的值
  • 第八步:race比promise.all更简单,执行完一个得到一个状态就输出

查漏补缺

上面粗略的实现了promise以及几个常用的方法,但是还有很多细节的地方没有处理好。这一篇继续查漏补缺,继续看下去吧

解决上一篇的promise会阻塞同步任务的问题

  • 利用Promise函数实现如下代码
let promise = new Promise((resolve, reject) => {
    resolve('data')
})
promise.then(res => {
    console.log(res)
})
console.log('end')
复制代码

输出:

image.png

  • 用上一篇的MyPromise函数执行和上面相同的代码
let promise = new MyPromise((resolve, reject) => {
    resolve('data')
})
promise.then(res => {
    console.log(res)
})
console.log('end')
复制代码

输出:

image.png

我们都知道promise.then是微任务,执行上面代码的时候先将整个代码作为宏任务开始执行,依次执行new Promise-->遇到promise.then放进微任务队列--->继续执行同步console.log("end")--->本次的宏任务执行完之后执行promise.then微任务,所以应该先输出end.

  • 解决方法:将promise.then(handleFulfilled, handleRejected),handleFulfilled和handleRejected调用的时候处理成异步任务。

这里先用setTimeout来模拟一下异步任务,比较方便。其实我们都知道promise.then是微任务

function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;
    that.onfufilledCallback = [];
    that.onrejectedCallback = [];

    function resolve(val) {
        setTimeout(() => {
            if (that.status == "pending") {
                that.status = 'fufilled';
                that.success = val;//保存当前成功的返回值
                that.onfufilledCallback.forEach(resolvefn => {
                    resolvefn(that.success);
                });
            }
        })
    }
    function reject(val) {
        setTimeout(() => {
            if (that.status == "pending") {
                that.status = 'rejected'
                that.error = val;
                that.onrejectedCallback.forEach(rejectfn => {
                    rejectfn(that.error);
                });//同步执行的时候缓存
            }
        })

    }
    executor(resolve, reject);
}
复制代码

在执行上面的代码输出:

image.png

new Promise((resolve,reject)=>{resolve(p1)}) resolve(p1)p1可以是一个promise对象

  • 利用Promise函数实现下面的代码
let promise = new Promise((resolve, reject) => {
    let p = new Promise((resolve2, reject2) => {
        resolve2('p222')
    })
    resolve(p)
})
promise.then(res => {
    console.log(res)
})
console.log('end')
复制代码

输出如下:resolve(p2),p2是一个promise也会帮我们执行并输出

image.png

  • 看看MyPromise代码执行的结果
let promise = new MyPromise((resolve, reject) => {
    let p = new MyPromise((resolve2, reject2) => {
        resolve2('p222')
    })
    resolve(p)
})
promise.then(res => {
    console.log(res)
})
console.log('end')
复制代码

输出的结果如下:

image.png

  • 解决方法,resolve函数里面判断是不是promise,如果是手动执行一次
function MyPromise(executor) {
    this.status = 'pending';//初始状态
    this.success = undefined;
    this.error = undefined;
    let that = this;
    that.onfufilledCallback = [];
    that.onrejectedCallback = [];

    function resolve(val) {
        if (val instanceof MyPromise) {
            return val.then(resolve, reject)
        }
        setTimeout(() => {
            if (that.status == "pending") {
                that.status = 'fufilled';
                that.success = val;//保存当前成功的返回值
                that.onfufilledCallback.forEach(resolvefn => {
                    resolvefn(that.success);
                });
            }
        })
    }
    function reject(val) {
        setTimeout(() => {
            if (that.status == "pending") {
                that.status = 'rejected'
                that.error = val;
                that.onrejectedCallback.forEach(rejectfn => {
                    rejectfn(that.error);
                });//同步执行的时候缓存
            }
        })

    }
    executor(resolve, reject);
}
复制代码

Promise穿透实现

  • 先用promise执行下面的代码
const promise = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })

        promise.then(null).then(res => {
            console.log(res)
        })
复制代码

输出:

image.png

  • 利用MyPromise执行上面同样代码
const promise = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })

        promise.then(null).then(res => {
            console.log(res)
        })
复制代码

输出结果:没有任何输出

  • 这其实是promise穿透现象:给then传递非函数值作为参数的时候,实际上会被解析成then(null).上一个Promise对象的执行结果会穿透到下一个then方法参数中=

在then函数里面处理一下,如果传入的不是函数,就将当前的参数包裹为一个函数 将then函数改造成如下:

MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
    handleFulfilled = typeof handleFulfilled == 'function' ? handleFulfilled : (data) => { return data }
    handleRejected = typeof handleRejected == 'function' ? handleRejected : (data) => { return data }
    let that = this;
    let mypromise2 = new MyPromise((resolve, reject) => {
        if (that.status == 'fufilled') {
            try {
                let res = handleFulfilled(this.success);//成功的值
                resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == 'rejected') {
            try {
                let err = handleRejected(this.error);//失败的值
                resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == 'pending') {

            //当函数调用的时候,去执行数组里面的函数
            that.onfufilledCallback.push(() => {
                try {
                    let res = handleFulfilled(this.success)
                    resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                } catch (e) {
                    reject(e)
                }
            });//这里的onfufulled就相当于then里面的第一个参数回调
            that.onrejectedCallback.push(() => {
                try {
                    let res = handleRejected(this.error);
                    resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                } catch (e) {
                    reject(e)
                }

            });
        }
    })
    return mypromise2
}
复制代码

附上代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        function MyPromise(executor) {

            this.status = 'pending';//初始状态
            this.success = undefined;
            this.error = undefined;
            let that = this;

            that.onfufilledCallback = [];
            that.onrejectedCallback = [];

            function resolve(val) {
                if (that.status == "pending") {
                    that.status = 'fufilled';
                    that.success = val;//保存当前成功的返回值
                    that.onfufilledCallback.forEach(resolvefn => {
                        resolvefn(that.success);
                    });
                }

            }
            function reject(val) {
                if (that.status == "pending") {
                    that.status = 'rejected'
                    that.error = val;
                    that.onrejectedCallback.forEach(rejectfn => {
                        rejectfn(that.error);
                    });//同步执行的时候缓存
                }
            }
            executor(resolve, reject);
        }

        MyPromise.prototype.then = function (handleFulfilled, handleRejected) {

            let that = this;
            let mypromise2 = new MyPromise((resolve, reject) => {

                if (that.status == 'fufilled') {
                    try {
                        let res = handleFulfilled(this.success);//成功的值
                        resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                    } catch (e) {
                        reject(e)
                    }
                }
                if (that.status == 'rejected') {
                    try {
                        let err = handleRejected(this.error);//失败的值
                        resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                    } catch (e) {
                        reject(e)
                    }
                }
                if (that.status == 'pending') {

                    //当函数调用的时候,去执行数组里面的函数
                    that.onfufilledCallback.push(() => {
                        try {
                            let res = handleFulfilled(this.success)
                            resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                        } catch (e) {
                            reject(e)
                        }
                    });//这里的onfufulled就相当于then里面的第一个参数回调
                    that.onrejectedCallback.push(() => {
                        try {
                            let res = handleRejected(this.error);
                            resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                        } catch (e) {
                            reject(e)
                        }

                    });
                }
            })
            return mypromise2
        }

        MyPromise.prototype.catch = function (callback) {
            return this.then(function () { }, callback)
        }
        MyPromise.prototype.all = function (values) {
            return new Promise(function (resolve, reject) {
                let num = 0;
                let arr = [];

                for (let i = 0; i < values.length; i++) {
                    let current = values[i];
                    if (current.then && typeof current.then == "function") {
                        //此时是promise对象
                        current.then.call(current, function (val) { //此时是执行完的结果
                            arr[i] = val
                            if (++num == values.length) {
                                resolve(arr)
                            }
                        }, reject)
                    } else {
                        //说明是具体的值
                        arr[i] = current
                        if (++num == values.length) {
                            resolve(arr)
                        }
                    }
                }
            })
        }

        MyPromise.prototype.race = function (values) {
            return new Promise(function (resolve, reject) {
                try {
                    let num = 0;
                    let arr = [];
                    let current
                    for (let i = 0; i < values.length; i++) {
                        current = values[i]
                        if (current.then && typeof current.then == "function") {
                            current.then(resolve, reject)
                        } else {
                            resolve(current)
                        }
                    }

                } catch (e) {
                    reject(e)
                }
            })
        }
        let mypromise = new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve("success"); //执行Promise里面的resolve函数的时候,会在执行that.onfufilledCallback ,相当于执行then的handleFulfilled方法
                reject("error");
            }, 2000)

        })
        mypromise.race([mypromise]).then(res => {
            console.log(res, "resssssssssss")
        }).catch(e => {
            console.log(e)
        })
    </script>
</body>

</html>
复制代码

完整代码(完善了一些细节)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        function MyPromise(executor) {
            this.status = 'pending';//初始状态
            this.success = undefined;
            this.error = undefined;
            let that = this;

            that.onfufilledCallback = [];
            that.onrejectedCallback = [];

            function resolve(val) {
                if (val instanceof MyPromise) {
                    return val.then(resolve, reject)
                }
                setTimeout(() => {
                    if (that.status == "pending") {
                        that.status = 'fufilled';
                        that.success = val;//保存当前成功的返回值
                        that.onfufilledCallback.forEach(resolvefn => {
                            resolvefn(that.success);
                        });
                    }
                })


            }
            function reject(val) {
                setTimeout(() => {
                    if (that.status == "pending") {
                        that.status = 'rejected'
                        that.error = val;
                        that.onrejectedCallback.forEach(rejectfn => {
                            rejectfn(that.error);
                        });//同步执行的时候缓存
                    }
                })

            }
            executor(resolve, reject);
        }

        MyPromise.prototype.then = function (handleFulfilled, handleRejected) {
            handleFulfilled = typeof handleFulfilled=='function'?handleFulfilled:(data)=>{return data}
            handleRejected = typeof handleRejected=='function'?handleRejected:(data)=>{return data}

            let that = this;
            let mypromise2 = new MyPromise((resolve, reject) => {

                if (that.status == 'fufilled') {
                    try {
                        let res = handleFulfilled(this.success);//成功的值
                        resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                    } catch (e) {
                        reject(e)
                    }
                }
                if (that.status == 'rejected') {
                    try {
                        let err = handleRejected(this.error);//失败的值
                        resolve(err);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                    } catch (e) {
                        reject(e)
                    }
                }
                if (that.status == 'pending') {

                    //当函数调用的时候,去执行数组里面的函数
                    that.onfufilledCallback.push(() => {
                        try {
                            let res = handleFulfilled(this.success)
                            resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                        } catch (e) {
                            reject(e)
                        }
                    });//这里的onfufulled就相当于then里面的第一个参数回调
                    that.onrejectedCallback.push(() => {
                        try {
                            let res = handleRejected(this.error);
                            resolve(res);//不管上一个then是成功还是失败第二个then都可以接收到上面返回的值
                        } catch (e) {
                            reject(e)
                        }

                    });
                }
            })
            return mypromise2
        }

        MyPromise.prototype.catch = function (callback) {
            return this.then(function () { }, callback)
        }
        MyPromise.prototype.all = function (values) {
            return new Promise(function (resolve, reject) {
                let num = 0;
                let arr = [];

                for (let i = 0; i < values.length; i++) {
                    let current = values[i];
                    if (current.then && typeof current.then == "function") {
                        //此时是promise对象
                        current.then.call(current, function (val) { //此时是执行完的结果
                            arr[i] = val
                            if (++num == values.length) {
                                resolve(arr)
                            }
                        }, reject)
                    } else {
                        //说明是具体的值
                        arr[i] = current
                        if (++num == values.length) {
                            resolve(arr)
                        }
                    }
                }
            })
        }

        MyPromise.prototype.race = function (values) {
            return new Promise(function (resolve, reject) {
                try {
                    let num = 0;
                    let arr = [];
                    let current
                    for (let i = 0; i < values.length; i++) {
                        current = values[i]
                        if (current.then && typeof current.then == "function") {
                            current.then(resolve, reject)
                        } else {
                            resolve(current)
                        }
                    }

                } catch (e) {
                    reject(e)
                }

            })
        }
        const promise = new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })
        promise.then(null).then(res => {
            console.log(res)
        })
    </script>
</body>

</html>
复制代码

最后分享一篇对我promise帮助很大的文章

要就来45道Promise面试题一次爽到底(1.1w字用心整理)

分类:
前端
标签: