方法 手写promise_手写Promise

edba98483b36ce90df277f04fc8f760a.png

在手写Promise之前,我们首先要理一下Promise的基本结构

基本结构

1.Promise是一个类, 在执行这个类的时候 需要传递一个执行器进去,执行器会立即执行

2.Promise 中有三个状态 分别是 成功(fulfilled)、失败(rejected)和等待(pending)

pending -> fulfilled

pending -> rejected

状态一旦确定就不可更改

3.resolve和reject函数是用来更改状态的

resolve: fulfilled

reject: rejected

4. then方法内部做的就是判断状态,如果是成功状态,调用成功回调函数,如果是失败状态,调用失败回调函数

5. then方法有两个回调,一个是成功回调,回调参数表示成功之后的值,一个是失败回调,回调参数表示失败的原因

明确了这些我们继续往下写

基本结构理清了我们先搭好架子

class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }

    // 更改为成功状态
    resolve = () => {
    }
    // 更改为失败状态
    reject = () => {
    }
}
module.exports = MyPromise;

增加状态

增加一个变量status记录当前实例状态,三种状态pending、fulfilled、rejected,初始值是pending ,在Promise中,状态一旦确定是不可更改的,所以在更改状态前要先进行判断状态是否是等待状态。

加入的代码

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    status = PENDING;
    // 更改为成功状态
    resolve = () => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
    }
    // 更改为失败状态
    reject = () => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
    }
}
module.exports = MyPromise;

加入then方法

then方法内部做的就是判断状态,如果是成功状态,调用成功回调函数,如果是失败状态,调用失败回调函数。

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    status = PENDING;
    // 更改为成功状态
    resolve = () => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
    }
    // 更改为失败状态
    reject = () => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
    }
    then(successCallback, failCallback) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallback()
        } else if (this.status === REJECTED) {
            failCallback()
        }
    }
}
module.exports = MyPromise;

then方法的回调参数

then有两个回调,一个是成功回调,回调参数表示成功之后的值,一个是失败回调,回调参数表示失败的原因,回调的参数是们调用成功回调或者失败回调所传入的值,所以这个值我们要要在resolve和reject中记录下来。

const PENDING = 'pending'; // 等待
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 = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
    }
    then(successCallback, failCallback) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallback(this.value)
        } else if (this.status === REJECTED) {
            failCallback(this.reason)
        }
    }
}
module.exports = MyPromise;

现在我们已经完成了一个最简单的Promise了,但是我们现在的代码没有考虑到异步的情况,接下来我们要给Promise中加入异步逻辑

给Promise加入异步逻辑

异步代码是会进入等待的,我们then方法要处理等待这种情况

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = undefined;
    // 失败回调
    failCallback = undefined;

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        this.successCallback && this.successCallback(this.value);

    }
    // 更改为失败状态
    reject = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在则调用
        this.failCallback && this.failCallback(this.reason);
    }
    then(successCallback, failCallback) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallback(this.value)
        } else if (this.status === REJECTED) {
            failCallback(this.reason)
        } else {
            // 等待状态 
            // 将成功回调和失败回调保存起来
            this.successCallback = successCallback;
            this.failCallback = failCallback;
        }
    }
}
module.exports = MyPromise;

现在我们是只考虑了只调用一次then方法的异步处理,then方法可以调用多次,有多个回调,我们都要保存下来,所以我们还要改造一下

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        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);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback, failCallback) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallback(this.value)
        } else if (this.status === REJECTED) {
            failCallback(this.reason)
        } else {
            // 等待状态 
            // 将成功回调和失败回调保存起来
            this.successCallback.push(successCallback);
            this.failCallback.push(failCallback);
        }
    }
}
module.exports = MyPromise;

then方法的链式调用

Promise中的then方法是可以链式调用的,后一个then方法的回调函数拿到的值实际上是上一个then方法的回调函数的返回值

改造一下代码:

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        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);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback, failCallback) {
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 将回调的结果传给下一个then方法
                const x = successCallback(this.value)
                resolve(x)
            } else if (this.status === REJECTED) {
                // 将回调的结果传给下一个then方法
                failCallback(this.reason)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        });
        return promise2
    }
}
module.exports = MyPromise;

在链式调用then方法的时候,在then方法的回调函数中,我们既可以返回一个promise对象,也可以返回一个普通值,如果我们返回的是一个普通值的话我们可以通过resolve方法把值传递给下一个promise对象,如果我们返回的是一个promise对象,我们要先查看promise对象的返回结果,如果这个结果是成功的,我们要调用resolve方法把值传递给下一个promise对象,如果这个结果是失败的,我们要调用reject方法把失败的原因传递给下一个promise对象,这个操作在三个状态中都有,所以我们抽出来写一个公共方法

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        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);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback, failCallback) {
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 将回调的结果传给下一个then方法
                const x = successCallback(this.value)
                // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                resolvePromise(x, resolve, reject)
            } else if (this.status === REJECTED) {
                // 将回调的结果传给下一个then方法
                failCallback(this.reason)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        });
        return promise2
    }
}
resolvePromise(x, resolve, reject) {
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

在then方法的回调函数当中,我们是不能返回当前这个then方法它所返回的promise对象的(有点绕,就是不能自己返回自己,promise的循环调用程序是不被允许的)例如下面这个例子

var promise = new Promise((resolve,reject) {
    resolve(100)
});
var p1 = promise.then(value => {
    console.log(value)
    // 自己返回自己
    return p1
})

p1.then(()=>,(reason) => {
    //打印报错结果
    console.log(reason.message)

})

我们的MyPromise中也要加入这样的逻辑

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 执行传入的函数参数
        executor(this.resolve, this.reject)
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        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);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback, failCallback) {
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
                setTimeout(() => {
                    // 将回调的结果传给下一个then方法
                    const x = successCallback(this.value)
                    // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                    // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                    resolvePromise(promise2, x, resolve, reject)
                }, 0)
            } else if (this.status === REJECTED) {
                // 将回调的结果传给下一个then方法
                failCallback(this.reason)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        });
        return promise2
    }
}
resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        // 自己返回自己 返回reject
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

捕捉错误及then链式调用其他状态代码补充

当执行器在执行过程当中发生错误的时候,我们就要让promise的状态变成失败的状态,也就是说我们要在then方法的第二个参数中捕获到这个错误,在其他的状态中也要加入这样的处理

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
        try {
            // 执行传入的函数参数
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e);
        }
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.successCallback.length) this.successCallback.shift()()
    }
    // 更改为失败状态
    reject = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在则调用
        // this.failCallback && this.failCallback(this.reason);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback, failCallback) {
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = successCallback(this.value);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = failCallback(this.reason);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = successCallback(this.value);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = failCallback(this.reason);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
            }
        });
        return promise2
    }
}
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // 自己返回自己 返回reject
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

将then方法的参数变成可选参数

then方法的两个参数都是可选参数,我们可以选择什么都不传,但是他的状态会一直传递给有回调函数的then

我们改进一下代码:

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
        try {
            // 执行传入的函数参数
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e);
        }
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.successCallback.length) this.successCallback.shift()()
    }
    // 更改为失败状态
    reject = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在则调用
        // this.failCallback && this.failCallback(this.reason);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => { throw reason };
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = successCallback(this.value);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = failCallback(this.reason);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = successCallback(this.value);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = failCallback(this.reason);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
            }
        });
        return promise2
    }
 }
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // 自己返回自己 返回reject
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

加入Promise.all()方法

Promise.all()方法允许我们按照异步代码调用的顺序得到异步代码执行的结果

Promise.all()方法接收一个数组,这个数组里面的我们可以填入任何值,包括普通值和Promise对象,数组当中值的顺序一定是我们得到的结果的顺序、

Promise.all()方法的返回值也是一个Promise对象,所以我们也可以链式调用then方法

在Promise.all()方法当中所有的Promise对象,如果他的状态都是成功的,那么all()方法它最后的结果就是成功的,如果有一个是失败的,那么它最后的结果就是失败的

all()方法是一个静态方法

代码实现:

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
        try {
            // 执行传入的函数参数
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e);
        }
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.successCallback.length) this.successCallback.shift()()
    }
    // 更改为失败状态
    reject = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在则调用
        // this.failCallback && this.failCallback(this.reason);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => { throw reason };
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = successCallback(this.value);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = failCallback(this.reason);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = successCallback(this.value);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = failCallback(this.reason);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
            }
        });
        return promise2
    }
    static all(array) {
        let result = [];
        // 为了等待异步任务的执行结果 我们定义一个index 当 index和数组的长度相等,说明所有任务都已完成
        let index = 0;
        return new MyPromise((resolve, reject) => {
            const addData = (key, value) => {
                result[key] = value;
                index++;
                if (index === array.length) {
                    resolve(result);
                }
            }
            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]);
                }
            }
        })
    }
}
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // 自己返回自己 返回reject
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

实现Promise.resolve()方法

Promise.resolve()方法的作用是将给定的的值转换成Promise对象,它也可以接收一个promise对象,resolve内部会判断你给定的值是普通值还是promise对象

resolve()是一个静态方法

代码实现:

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
        try {
            // 执行传入的函数参数
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e);
        }
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.successCallback.length) this.successCallback.shift()()
    }
    // 更改为失败状态
    reject = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在则调用
        // this.failCallback && this.failCallback(this.reason);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => { throw reason };
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = successCallback(this.value);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = failCallback(this.reason);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = successCallback(this.value);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = failCallback(this.reason);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
            }
        });
        return promise2
    }
    static all(array) {
        let result = [];
        // 为了等待异步任务的执行结果 我们定义一个index 当 index和数组的长度相等,说明所有任务都已完成
        let index = 0;
        return new MyPromise((resolve, reject) => {
            const addData = (key, value) => {
                result[key] = value;
                index++;
                if (index === array.length) {
                    resolve(result);
                }
            }
            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]);
                }
            }
        })
    }
    static resolve(value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value))
    }
}
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // 自己返回自己 返回reject
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

Promise.finally()和Promise.catch()方法实现

无论当前promise的最终状态是成功的还是失败的finally方法当中的回调函数始终都会被执行一次,在finally()方法后面我们可以链式调用then方法拿到当前promise对象最终的返回结果

catch()方法的作用是用来处理当前promise对象最终的状态为失败的情况的,当我们调用then方法是可以不传递失败回调的,如果我们不传递失败回调,那么失败回调就会被catch方法捕获从而去执行传入到catch方法当中的回调函数

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
    constructor(executor) {
        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
        try {
            // 执行传入的函数参数
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e);
        }
    }
    // Promise状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];

    // 更改为成功状态
    resolve = value => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在则调用
        // this.successCallback && this.successCallback(this.value);

        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.successCallback.length) this.successCallback.shift()()
    }
    // 更改为失败状态
    reject = reason => {
        // 如果不是等待状态 就阻止程序向下执行
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在则调用
        // this.failCallback && this.failCallback(this.reason);
        // 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
        // 每当执行一次数组就会删除一个,数组长度为零时就不再执行
        while (this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => { throw reason };
        // 创建一个新的promise对象 并返回
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = successCallback(this.value);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                    try {
                        // 将回调的结果传给下一个then方法
                        const x = failCallback(this.reason);
                        // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                        // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        // 调用下一个promise的reject方法
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态 
                // 将成功回调和失败回调保存起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = successCallback(this.value);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        // 加入try、catch 如果执行器中出现错误就调用reject更改状态
                        try {
                            // 将回调的结果传给下一个then方法
                            const x = failCallback(this.reason);
                            // 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
                            // 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 调用下一个promise的reject方法
                            reject(e);
                        }
                    }, 0)
                });
            }
        });
        return promise2
    }
    finally(callback) {
        // 调用then方法拿到当前promise的状态
        return this.then(value => {
            // 调用MyPromise.resolve处理callback()返回的结果,并返回
            return MyPromise.resolve(callback()).then(() => value)
        }, reason => {
            return MyPromise.resolve(callback()).then(() => { throw reason })
        })
    }
    catch (failCallback) {
        return this.then(undefined, failCallback)
    }
    static all(array) {
        let result = [];
        // 为了等待异步任务的执行结果 我们定义一个index 当 index和数组的长度相等,说明所有任务都已完成
        let index = 0;
        return new MyPromise((resolve, reject) => {
            const addData = (key, value) => {
                result[key] = value;
                index++;
                if (index === array.length) {
                    resolve(result);
                }
            }
            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]);
                }
            }
        })
    }
    static resolve(value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value))
    }
}
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // 自己返回自己 返回reject
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // 是promise对象
        // x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
        x.then(resolve, reject)
    } else {
        // 是普通值 直接返回
        resolve(x)

    }
}
module.exports = MyPromise;

这样一个Promise就实现完成了!

  • 文章内容输出来源:拉勾教育前端高薪训练营;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值