• Promise原理及实现


    1 Promise核心逻辑实现

    Promise对象是一个原生的javascript对象,是一种异步编程的解决方案,它通过一个回调,可以避免更多的回调,接下来说明其原理及实现。

    下面一段代码是Promise的基本使用:

    new Promise((resolve, reject) => {
        resolve("成功");
        reject("失败");
    })
    Promise.then(value => { }, reason => { })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    从上面的代码中,我们可以分析出一些关键点:

    1. Promise创建时需要使用new关键字,那么我们可以知道Promise就是一个类
    2. 在执行这个类的时候,需要传递一个执行器进去,这个执行器会立即执行
    3. 在执行器中有两个参数,resolvereject,它们都是函数,用来改变Promise中的状态
    4. Promise中有三种状态,分别是:成功fulfilled、失败rejected和等待pending,状态只能从pending—>fulfilled,或者pending—>rejected状态一旦确定就不可以更改
    5. resolvereject函数是用来更改状态的,其中,resolve将状态更改为fulfilledreject将状态更改为rejected
    6. then方法接收两个函数作为参数,它需要判断状态,如果成功调用第一个回调函数,如果失败调用第二个回调函数,并且then方法是被定义在原型对象中的,第一个回调函数的参数为成功之后的值,第二个回调函数的参数为失败之后的原因;

    接下来我们根据上面分析出的内容,一步一步实现我们自己的Promise。

    首先创建一个类,为constructor构造函数传入一个执行器,因为执行器需要立即执行,因此在构造函数中调用该执行器。

    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(); // 执行器会立即执行
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在执行器中有两个参数resolvereject,它们都是函数,因此在类中创建两个箭头函数resolvereject,在执行器executor中使用this来调用它们。

    为什么使用箭头函数:
    注意,我们在Promise中调用resolvereject是直接调用的,如果将它们写成普通函数,那么会将this指向window或者undefined,如果我们写成箭头函数,那么它们的this就会指向类的实例对象。

    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
        resolve = () => {
    
        }
        reject = () => {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    resolvereject这两个函数是用来改变状态的,因此我们将状态定义在类的外面,因为它们会被频繁使用到。在类中我们默认定义状态status是等待pending,当调用resolve时,状态改为成功,当调用reject时,状态改为失败。并且状态一旦确定不可更改,因此我们要在两个函数中判断当前状态是否为等待,不是则返回。

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
    
        status = PENDING; // 状态默认为pending等待
    
        resolve = () => {
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = FULFILLED; // 将状态改为成功
        }
    
        reject = () => {
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = REJECTED; // 将状态改为失败
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Promise中的then方法有两个参数,当状态成功调用第一个,状态失败调用第二个,因此内部需要使用if来判断状态。调用成功或者失败函数时,需要为其传入参数,那么我们知道成功的值是由resolve传递来的,失败的原因是由reject传递来的,因此我们在Promise中声明两个属性存放两个值。

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
    
        resolve = value => { // value是成功之后的值
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = FULFILLED; // 将状态改为成功
            this.value = value; // 将成功的值传递
        }
    
        reject = reason => { // reason是失败之后的原因
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = REJECTED; // 将状态改为失败
            this.reason = reason; // 将失败的值传递
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                successCallback(this.value);
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                failCallback(this.reason);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    到这里我们就实现了一个最简单的Promise了。

    2 加入异步逻辑

    上面我们实现的Promise,实际上并没有考虑异步情况,比如说下面的代码中,2秒后调用成功的回调,如果这时调用then方法,那么当前的状态是等待pending,但是我们并没有判断状态是pending时的情况。

    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("成功");
        }, 2000);
    })
    Promise.then(value => { }, reason => { })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    因此在then方法中,我们应该判断当状态是等待的情况。当状态是等待时,我们没有办法调用成功或者失败的回调,这时我们需要将成功回调和失败回调储存起来。

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = undefined; // 成功的回调函数
        failCallback = undefined; // 失败的回调函数
    
        resolve = value => { // value是成功之后的值
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = FULFILLED; // 将状态改为成功
            this.value = value; // 将成功的值传递
        }
    
        reject = reason => { // reason是失败之后的原因
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = REJECTED; // 将状态改为失败
            this.reason = reason; // 将失败的值传递
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                successCallback(this.value);
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                failCallback(this.reason);
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback = successCallback;
                this.failCallback = failCallback;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    将成功回调和失败回调存储起来之后,我们则要在resolvereject方法中判断是否存在成功或者失败的回调,如果存在,则将其调用。

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = undefined; // 成功的回调函数
        failCallback = undefined; // 失败的回调函数
    
        resolve = value => { // value是成功之后的值
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = FULFILLED; // 将状态改为成功
            this.value = value; // 将成功的值传递
            this.successCallback && this.successCallback(this.value); // 如果成功回调存在,则调用
        }
    
        reject = reason => { // reason是失败之后的原因
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = REJECTED; // 将状态改为失败
            this.reason = reason; // 将失败的值传递
            this.failCallback && this.failCallback(this.reason); // 如果失败回调存在,则调用
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                successCallback(this.value);
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                failCallback(this.reason);
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback = successCallback;
                this.failCallback = failCallback;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    这是我们就处理了异步的情况了。

    3 then方法添加多次调用逻辑

    Promise的then方法可以调用多次,我们接着处理这部分。

    let promise = new Promise((resolve, reject) => { })
    promise.then(value => { })
    promise.then(value => { })
    promise.then(value => { })
    
    • 1
    • 2
    • 3
    • 4

    如果多次调用了then方法,就需要考虑两种情况:同步情况和异步情况。如果是同步情况,那么直接就可以调用回调函数,我们已经不需要多做处理了,如果是异步情况,那么我们需要将每一个回调函数储存起来。

    我们之前在then方法中判断等待的时候,也将成功和失败的回调存储起来,但是每次只能存储一个,因此我们需要将存储的容器设为数组,通过数组的push方法将回调函数存储起来。

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = []; // 使用数组存储成功的回调函数
        failCallback = []; // 使用数组存储失败的回调函数
    
        resolve = value => { // value是成功之后的值
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = FULFILLED; // 将状态改为成功
            this.value = value; // 将成功的值传递
            this.successCallback && this.successCallback(this.value); // 如果成功回调存在,则调用
        }
    
        reject = reason => { // reason是失败之后的原因
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = REJECTED; // 将状态改为失败
            this.reason = reason; // 将失败的值传递
            this.failCallback && this.failCallback(this.reason); // 如果失败回调存在,则调用
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                successCallback(this.value);
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                failCallback(this.reason);
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    更改成数组之后,那么我们原来在resolvereject函数中调用成功或者失败的回调函数就不可以使用了,而是在其中循环调用数组中的回调函数。

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            executor(this.resolve, this.reject); // 执行器会立即执行
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = []; // 成功的回调函数
        failCallback = []; // 失败的回调函数
    
        resolve = value => { // value是成功之后的值
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = FULFILLED; // 将状态改为成功
            this.value = value; // 将成功的值传递
            while (this.successCallback.length) { // 循环执行数组中的回调函数
                this.successCallback.shift()(this.value); // 调用回调函数
            }
        }
    
        reject = reason => { // reason是失败之后的原因
            if (this.status !== PENDING) return; // 当状态不是等待,直接返回
            this.status = REJECTED; // 将状态改为失败
            this.reason = reason; // 将失败的值传递
            while (this.failCallback.length) { // 循环执行
                this.failCallback.shift()(this.value); // 调用失败回调函数
            }
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                successCallback(this.value);
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                failCallback(this.reason);
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    4 链式调用then方法

    Promise的then方法可以链式调用,下一个then方法中成功回调函数的参数是上一个then方法中的回调函数的返回值,也就是说,在下面代码中,value的值为1。

    let promise = new Promise((resolve, reject) => { });
    promise.then(() => { return 1 })
        .then(value => { })
        .then(() => { })
    
    • 1
    • 2
    • 3
    • 4

    我们首先来实现then方法的链式调用。then方法是Promise中的方法,如果要实现链式调用,那么每个then方法都应该返回一个Promise对象,这样才可以调用。那么我们应该在then方法中创建一个Promise对象,最后返回这个对象就可以。除此之外,我们还需要将then方法中原来的代码传入到新创建对象的执行器中,保证调用方法后就立即执行。

    then(successCallback, failCallback) { // then方法有两个参数
        let promise = new MyPromise(() => {
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                successCallback(this.value);
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                failCallback(this.reason);
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        })
        return promise;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    那么链式调用的问题就解决了,我们还需要将本次回调函数的返回值传到下一个then的成功回调函数中。因此,我们需要获取到成功和失败回调函数的返回值,并将其通过新promise对象的resolve方法传递过去。

    then(successCallback, failCallback) { // then方法有两个参数
        let promise = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                let result = successCallback(this.value);
                resolve(result); // 将返回值传递到下一个回调函数
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                let result = failCallback(this.reason);
                resolve(result);
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        })
        return promise;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    如果上一次回调函数的返回值是一个Promise对象,我们就需要查看Promise对象的状态,如果状态成功,则调用resolve将状态传递给下一个Promise对象,如果状态失败,则调用reject将失败信息传递。我们需要写一个方法resolvePromise,用来判断这些逻辑。

    function resolvePromise(result, resolve, reject) {
        // 通过判断result是不是MyPromise的实例对象来判断是不是Promise对象
        if (result instanceof MyPromise) { // 是Promise对象
            // 调用then方法查看Promise对象的状态
            // 如果成功调用第一个回调函数,如果失败调用第二个回调函数
            result.then(value => resolve(value), reason => reject(reason));
        } else { // 如果是普通值
            resolve(result); // 直接将普通值传递
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    那么在then方法中调用resolvePromise函数:

        then(successCallback, failCallback) { // then方法有两个参数
            let promise = new MyPromise((resolve, reject) => {
                if (this.status === FULFILLED) { // 成功调用第一个回调函数
                    let result = successCallback(this.value);
                    resolvePromise(result, resolve, reject); // 调用方法
                } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                	let result = failCallback(this.reason);
                    resolvePromise(result, resolve, reject);
                } else { // 当状态为等待时,将成功回调和失败回调存储起来
                    this.successCallback.push(successCallback);
                    this.failCallback.push(failCallback);
                }
            })
            return promise;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在上面我们知道then方法中可以返回Promise对象,那么如果返回的Promise对象还是then方法中接收到的Promise对象,则会形成循环调用,这时应该报出错误。我们在then方法中拿到了返回值result,因此只需要判断它是不是和promise相同即可。我们将这个逻辑也写在resolvePromise函数中。

    function resolvePromise(promise, result, resolve, reject) {
        if (promise === result) { // 如果相同,报错
            reject(new TypeError("promise对象循环了"));
            return; // 阻止代码向下执行
        }
        // 通过判断result是不是MyPromise的实例对象来判断是不是Promise对象
        if (result instanceof MyPromise) { // 是Promise对象
            // 调用then方法查看Promise对象的状态
            // 如果成功调用第一个回调函数,如果失败调用第二个回调函数
            result.then(value => resolve(value), reason => reject(reason));
        } else { // 如果是普通值
            resolve(result); // 直接将普通值传递
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    then方法中也调用上面的函数。但是实际上我们在then方法中是获取不到promise的,因为promise在实例化之后才可以获取到,这时我们可以将状态成功时的代码变成异步代码,让同步代码先执行完成,执行完成之后再执行异步代码。我们可以使用setTimeout定时器来使其变成异步代码。

    then(successCallback, failCallback) { // then方法有两个参数
        let promise = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                setTimeout(() => { // 变成异步代码,获取promise
                    let result = successCallback(this.value);
                    resolvePromise(promise, result, resolve, reject); // 调用方法
                }, 0)
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                setTimeout(() => {
                	let result = failCallback(this.reason);
                    resolvePromise(promise, result, resolve, reject);
                }, 0)
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback.push(successCallback);
                this.failCallback.push(failCallback);
            }
        })
        return promise;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    全部代码如下:

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            try {
                executor(this.resolve, this.reject); // 执行器会立即执行
            } catch (e) {
                this.reject(e); // 将错误原因传递给失败回调函数
            }
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = []; // 成功的回调函数
        failCallback = []; // 失败的回调函数
    
        resolve = value => { // 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 => { // 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.value); // 调用失败回调函数
            }
        }
    
    	then(successCallback, failCallback) { // then方法有两个参数
    	    let promise = new MyPromise((resolve, reject) => {
    	        if (this.status === FULFILLED) { // 成功调用第一个回调函数
    	            setTimeout(() => { // 变成异步代码,获取promise
    	                let result = successCallback(this.value);
    	                resolvePromise(promise, result, resolve, reject); // 调用方法
    	            }, 0)
    	        } else if (this.status === REJECTED) { // 失败调用第二个回调函数
    	            setTimeout(() => {
    	            	let result = failCallback(this.reason);
    	                resolvePromise(promise, result, resolve, reject);
    	            }, 0)
    	        } else { // 当状态为等待时,将成功回调和失败回调存储起来
    	            this.successCallback.push(successCallback);
    	            this.failCallback.push(failCallback);
    	        }
    	    })
    	    return promise;
    	}
    }
    
    function resolvePromise(promise, result, resolve, reject) {
        if (promise === result) { // 如果相同,报错
            reject(new TypeError("promise对象循环了"));
            return; // 阻止代码向下执行
        }
        // 通过判断result是不是MyPromise的实例对象来判断是不是Promise对象
        if (result instanceof MyPromise) { // 是Promise对象
            // 调用then方法查看Promise对象的状态
            // 如果成功调用第一个回调函数,如果失败调用第二个回调函数
            result.then(value => resolve(value), reason => reject(reason));
        } else { // 如果是普通值
            resolve(result); // 直接将普通值传递
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    5 Promise错误捕获

    1、捕获执行器错误。当执行器错误时,直接执行reject方法,这个错误实际上是在then方法中的失败回调函数中输出的。

    constructor(executor) { // 接收一个执行器
        try {
            executor(this.resolve, this.reject); // 执行器会立即执行
        } catch (e) {
            this.reject(e); // 将错误原因传递给失败回调函数
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2、捕获then方法中回调函数的错误。如果当前then方法中的回调函数错误,那么应该在下一个then方法中的失败回调函数中输出。

        then(successCallback, failCallback) { // then方法有两个参数
            let promise = new MyPromise((resolve, reject) => {
                if (this.status === FULFILLED) { // 成功调用第一个回调函数
                    setTimeout(() => { // 变成异步代码,获取promise
                        try {
                            let result = successCallback(this.value);
                            resolvePromise(promise, result, resolve, reject); // 调用方法
                        } catch (e) {
                            reject(e); // 将错误传递到下一个then中
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                    setTimeout(() => {
                        try {
                            let result = failCallback(this.reason);
                            resolvePromise(promise, result, resolve, reject);
                        } catch (e) {
                            reject(e); // 传递错误
                        }
                    }, 0)
                } else { // 当状态为等待时,将成功回调和失败回调存储起来
                    this.successCallback.push(successCallback);
                    this.failCallback.push(failCallback);
                }
            })
            return promise;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    当状态为等待时,也需要为它进行错误处理。状态为等待时,数组中原本存入了成功和失败的回调,但是这样没有办法进行错误处理,因此我们可以在数组中存入一个回调函数,回调函数内部调用成功或者失败的函数。

    then(successCallback, failCallback) { // then方法有两个参数
        let promise = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) { // 成功调用第一个回调函数
                setTimeout(() => { // 变成异步代码,获取promise
                    try {
                        let result = successCallback(this.value);
                        resolvePromise(promise, result, resolve, reject); // 调用方法
                    } catch (e) {
                        reject(e); // 将错误传递到下一个then中
                    }
                }, 0)
            } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                setTimeout(() => {
                    try {
                        let result = failCallback(this.reason);
                        resolvePromise(promise, result, resolve, reject);
                    } catch (e) {
                        reject(e); // 传递错误
                    }
                }, 0)
            } else { // 当状态为等待时,将成功回调和失败回调存储起来
                this.successCallback.push(() => { // 为数组添加成功回调函数
                    setTimeout(() => { // 变成异步代码,获取promise
                        try {
                            let result = successCallback(this.value);
                            resolvePromise(promise, result, resolve, reject); // 调用方法
                        } catch (e) {
                            reject(e); // 将错误传递到下一个then中
                        }
                    }, 0)
                });
                this.failCallback.push(() => { // 为数组添加失败回调函数
                    setTimeout(() => {
                        try {
                            let result = failCallback(this.reason);
                            resolvePromise(promise, result, resolve, reject);
                        } catch (e) {
                            reject(e); // 传递错误
                        }
                    }, 0)
                });
            }
        })
        return promise;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    那么在resolvereject函数中,调用成功和失败函数的逻辑也需要修改一下:

    // 局部代码
    this.successCallback.shift()(); // 调用回调函数
    this.failCallback.shift()(); // 调用失败回调函数
    
    • 1
    • 2
    • 3

    全部代码:

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            try {
                executor(this.resolve, this.reject); // 执行器会立即执行
            } catch (e) {
                this.reject(e); // 将错误原因传递给失败回调函数
            }
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = []; // 成功的回调函数
        failCallback = []; // 失败的回调函数
    
        resolve = value => { // 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()(); // 调用回调函数
            }
        }
    
        reject = reason => { // 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()(); // 调用失败回调函数
            }
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            let promise = new MyPromise((resolve, reject) => {
                if (this.status === FULFILLED) { // 成功调用第一个回调函数
                    setTimeout(() => { // 变成异步代码,获取promise
                        try {
                            let result = successCallback(this.value);
                            resolvePromise(promise, result, resolve, reject); // 调用方法
                        } catch (e) {
                            reject(e); // 将错误传递到下一个then中
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                    setTimeout(() => {
                        try {
                            let result = failCallback(this.reason);
                            resolvePromise(promise, result, resolve, reject);
                        } catch (e) {
                            reject(e); // 传递错误
                        }
                    }, 0)
                } else { // 当状态为等待时,将成功回调和失败回调存储起来
                    this.successCallback.push(() => { // 为数组添加成功回调函数
                        setTimeout(() => { // 变成异步代码,获取promise
                            try {
                                let result = successCallback(this.value);
                                resolvePromise(promise, result, resolve, reject); // 调用方法
                            } catch (e) {
                                reject(e); // 将错误传递到下一个then中
                            }
                        }, 0)
                    });
                    this.failCallback.push(() => { // 为数组添加失败回调函数
                        setTimeout(() => {
                            try {
                                let result = failCallback(this.reason);
                                resolvePromise(promise, result, resolve, reject);
                            } catch (e) {
                                reject(e); // 传递错误
                            }
                        }, 0)
                    });
                }
            })
            return promise;
        }
    }
    
    function resolvePromise(promise, result, resolve, reject) {
        if (promise === result) { // 如果相同,报错
            reject(new TypeError("promise对象循环了"));
            return; // 阻止代码向下执行
        }
        // 通过判断result是不是MyPromise的实例对象来判断是不是Promise对象
        if (result instanceof MyPromise) { // 是Promise对象
            // 调用then方法查看Promise对象的状态
            // 如果成功调用第一个回调函数,如果失败调用第二个回调函数
            result.then(value => resolve(value), reason => reject(reason));
        } else { // 如果是普通值
            resolve(result); // 直接将普通值传递
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

    6 then方法参数设置为可选

    如果then方法中没有参数,那么它的参数应该传到之后的then方法中。

    let p = new Promise((resolve, reject) => { resolve(100) })
    p.then().then().then(value => console.log(value)); // 100
    
    • 1
    • 2

    那么我们可以在then方法中判断是否传入了参数,如果没有直接传到下一个then方法中。

        then(successCallback, failCallback) { // then方法有两个参数
            // 如果没有传入参数,则将值返回
            successCallback = successCallback ? successCallback : value => value;
            failCallback = failCallback ? failCallback : reason => reason => { throw reason };
            
            let promise = new MyPromise((resolve, reject) => {
                if (this.status === FULFILLED) { // 成功调用第一个回调函数
                    setTimeout(() => { // 变成异步代码,获取promise
                        try {
                            let result = successCallback(this.value);
                            resolvePromise(promise, result, resolve, reject); // 调用方法
                        } catch (e) {
                            reject(e); // 将错误传递到下一个then中
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                    setTimeout(() => {
                        try {
                            let result = failCallback(this.reason);
                            resolvePromise(promise, result, resolve, reject);
                        } catch (e) {
                            reject(e); // 传递错误
                        }
                    }, 0)
                } else { // 当状态为等待时,将成功回调和失败回调存储起来
                    this.successCallback.push(() => { // 为数组添加成功回调函数
                        setTimeout(() => { // 变成异步代码,获取promise
                            try {
                                let result = successCallback(this.value);
                                resolvePromise(promise, result, resolve, reject); // 调用方法
                            } catch (e) {
                                reject(e); // 将错误传递到下一个then中
                            }
                        }, 0)
                    });
                    this.failCallback.push(() => { // 为数组添加失败回调函数
                        setTimeout(() => {
                            try {
                                let result = failCallback(this.reason);
                                resolvePromise(promise, result, resolve, reject);
                            } catch (e) {
                                reject(e); // 传递错误
                            }
                        }, 0)
                    });
                }
            })
            return promise;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    7 实现Promise.all

    Promise.all方法接收一个数组作为参数,它允许我们按照异步代码调用的顺序得到异步代码的结果,也就是说,它的输出结果就是参数的传递顺序。这个方法有几点需要注意:

    • Promise.all方法的返回值也是一个Promise对象,也就是说,它也可以链式调用then方法;
    • Promise.all中所有结果都是成功的,那么结果就是成功的,如果有一个结果是失败的,那么它就是失败的;
    Promise.all(["a", "b", p1(), p2(), "c"]).then(result => {
        // result -> ["a", "b", p1(), p2(), "c"]
    })
    
    • 1
    • 2
    • 3

    首先,我们看到all方法是Promise类名直接调用的,说明它是一个静态方法。它接受了一个数组作为参数,最终返回了一个Promise对象,那么基本框架我们可以写出来了:

    static all(array) {
        return new MyPromise((resolve, reject) => {
        })
    }
    
    • 1
    • 2
    • 3
    • 4

    接着我们应该判断传入的参数是普通值还是Promise对象,如果是普通值,那么直接放到结果数组中,如果是Promise对象,那么我们就先执行这个Promise对象,再将执行后的结果放到结果数组当中。将结果添加到结果数组中时,我们定义一个函数addData来帮助我们。当循环执行完成之后,我们应该调用resolve方法将result结果数组传递到外面。

    static all(array) {
        let result = []; // 结果数组,用来存放结果
    
        function addData(key, value) { // 将结果添加到结果数组中
            result[key] = value;
        }
    
        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                let current = array[i]; // 获取当前的值
                if (current instanceof MyPromise) { // 是一个Promise对象
                    // 如果是一个Promise对象,我们首先要执行这个对象
                    // 调用它的then方法,如果成功将结果添加到数组中,失败则传递错误
                    current.then(value => addData(i, value), reason => reject(reason))
                } else { // 是一个普通值
                    addData(i, array[i]); // 普通值直接将结果添加到数组中
                }
            }
            resolve(result); // 将结果传递出去
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    但是这里会出现一个问题,for循环是一瞬间执行完成了,如果Promise中有异步代码,那么异步代码并没有执行完就执行resolve方法,那么我们最终拿不到异步任务的结果。所以我们可以设置一个计数器index,当结果数组中有一个结果,就让计数器+1,当计数器的值等于数组array的长度时,才能执行resolve方法。

    static all(array) {
        let result = []; // 结果数组,用来存放结果
        let index = 0; // 计数器,记录是否执行完成
    
        return new MyPromise((resolve, reject) => {
        	// addData方法在数组中才能执行resolve
            function 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对象
                    // 如果是一个Promise对象,我们首先要执行这个对象
                    // 调用它的then方法,如果成功将结果添加到数组中,失败则传递错误
                    current.then(value => addData(i, value), reason => reject(reason))
                } else { // 是一个普通值
                    addData(i, array[i]); // 普通值直接将结果添加到数组中
                }
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    8 实现Promise.resolve

    Promise.resolve方法会将给定的值转换成Promise对象,也就是说它的返回值就是一个Promise对象。

    Promise.resolve(10).then(value => console.log(value));
    
    • 1

    Promise.resolve方法是一个静态方法,在该方法内部会判断参数是否为Promise对象,如果是,则原封不动返回,如果不是,就创建一个Promise对象,将给定的值包裹在Promise对象当中,最后返回即可。

    static resolve(value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value));
    }
    
    • 1
    • 2
    • 3
    • 4

    9 实现Promise.race

    Promise.race参数是数组,它会返回一个Promise对象,一旦某个参数先改变状态,那么直接就将该状态返回,也就是说,看谁执行的更快。

    Promise.race(["a", "b", "c"]).then(value => console.log(value));
    
    • 1

    Promise.race方法是一个静态方法,它接受一个数组作为参数,最后返回一个Promise对象,基础框架如下:

    static race(array) {
        return new MyPromise((reslve, reject) => { })
    }
    
    • 1
    • 2
    • 3

    循环遍历参数,返回第一个成功或者失败的结果。

    static race(array) {
        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                Promise.resolve(array[i]).then(value => resolve(value), reason => reject(reason));
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    10 实现finally方法

    finally方法接受一个回调函数作为参数,它有一些特点:

    • 无论最后Promise对象最终的状态是成功的还是失败的,该方法中回调函数都会被执行一次
    • finally方法后可以链式调用then方法拿到当前Promise对象最终返回的结果。
    let promise = new Promise();
    promise.finally(() => console.log("finally")).then(value => console.log(value));
    
    • 1
    • 2

    首先我们要获得Promise对象的状态,我们可以调用then方法来获得状态。由于无论状态成功还是失败,我们都要调用回调函数,因此在then方法中成功和失败中都调用一次该回调函数。由于finally返回Promise对象,then方法也返回Promise对象,因此我们直接将then方法返回即可。

    finally(callBack) {
        return this.then(() => {
            callBack(); // 成功的回调函数中调用
        }, () => {
            callBack(); // 失败的回调函数中调用
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    接着,我们需要在成功的回调函数中返回成功的值,在失败的回调函数中传递失败的原因。

    finally(callBack) {
        return this.then(value => {
            callBack(); // 成功的回调函数中调用
            return value; // 将成功的值返回
        }, reason => {
            callBack(); // 失败的回调函数中调用
            throw reason; // 将失败原因传递下去
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果在finally后面的then中返回了一个Promise对象,对象中有异步代码,那么我们应该等待异步代码执行完成之后,再继续执行后面的then方法。所以我们应该判断callBack的返回值是什么,如果是一个普通值,我们将其转换为Promise对象,等待其执行完成,如果是一个Promise对象,我们还是等待其执行完成。

    finally(callBack) {
        return this.then(value => {
            return MyPromise.resolve(callBack()).then(() => value);
        }, reason => {
            return MyPromise.resolve(callBack()).then(() => { throw reason });
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    11 实现catch方法

    catch方法用来处理Promise对象最终为失败的情况,当我们调用then方法是,是可以不传递失败回调的,那么失败回调会被catch方法所捕获。

    let promise = new Promise();
    promise.then(value => console.log(value)).catch(reason => console.log(reason));
    
    • 1
    • 2

    catch方法接受一个回调函数作为参数,在其内部调用then方法,并且不传递成功回调,只传递失败回调函数,最后将then方法返回即可。

    catch(failCallback) {
        return this.then(undefined, failCallback);
    }
    
    • 1
    • 2
    • 3

    12 全部代码展示

    const PENDING = "pending"; // 等待
    const FULFILLED = "fulfilled"; // 成功
    const REJECTED = "rejected"; // 失败
    
    class MyPromise {
        constructor(executor) { // 接收一个执行器
            try {
                executor(this.resolve, this.reject); // 执行器会立即执行
            } catch (e) {
                this.reject(e); // 将错误原因传递给失败回调函数
            }
        }
    
        status = PENDING; // 状态默认为pending等待
        value = undefined; // 成功之后的值
        reason = undefined; // 失败之后的原因
        successCallback = []; // 成功的回调函数
        failCallback = []; // 失败的回调函数
    
        resolve = value => { // 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()(); // 调用回调函数
            }
        }
    
        reject = reason => { // 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()(); // 调用失败回调函数
            }
        }
    
        then(successCallback, failCallback) { // then方法有两个参数
            // 如果没有传入参数,则将值返回
            successCallback = successCallback ? successCallback : value => value;
            failCallback = failCallback ? failCallback : reason => { throw reason };
    
            let promise = new MyPromise((resolve, reject) => {
                if (this.status === FULFILLED) { // 成功调用第一个回调函数
                    setTimeout(() => { // 变成异步代码,获取promise
                        try {
                            let result = successCallback(this.value);
                            resolvePromise(promise, result, resolve, reject); // 调用方法
                        } catch (e) {
                            reject(e); // 将错误传递到下一个then中
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 失败调用第二个回调函数
                    setTimeout(() => {
                        try {
                            let result = failCallback(this.reason);
                            resolvePromise(promise, result, resolve, reject);
                        } catch (e) {
                            reject(e); // 传递错误
                        }
                    }, 0)
                } else { // 当状态为等待时,将成功回调和失败回调存储起来
                    this.successCallback.push(() => { // 为数组添加成功回调函数
                        setTimeout(() => { // 变成异步代码,获取promise
                            try {
                                let result = successCallback(this.value);
                                resolvePromise(promise, result, resolve, reject); // 调用方法
                            } catch (e) {
                                reject(e); // 将错误传递到下一个then中
                            }
                        }, 0)
                    });
                    this.failCallback.push(() => { // 为数组添加失败回调函数
                        setTimeout(() => {
                            try {
                                let result = failCallback(this.reason);
                                resolvePromise(promise, result, resolve, reject);
                            } catch (e) {
                                reject(e); // 传递错误
                            }
                        }, 0)
                    });
                }
            })
            return promise;
        }
    
        finally(callBack) {
            return this.then(value => {
                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 = []; // 结果数组,用来存放结果
            let index = 0; // 计数器,记录是否执行完成
    
            return new MyPromise((resolve, reject) => {
                function 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对象
                        // 如果是一个Promise对象,我们首先要执行这个对象
                        // 调用它的then方法,如果成功将结果添加到数组中,失败则传递错误
                        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));
        }
    
        static race(array) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < array.length; i++) {
                    Promise.resolve(array[i]).then(value => resolve(value), reason => reject(reason));
                }
            })
        }
    }
    
    function resolvePromise(promise, result, resolve, reject) {
        if (promise === result) { // 如果相同,报错
            reject(new TypeError("promise对象循环了"));
            return; // 阻止代码向下执行
        }
        // 通过判断result是不是MyPromise的实例对象来判断是不是Promise对象
        if (result instanceof MyPromise) { // 是Promise对象
            // 调用then方法查看Promise对象的状态
            // 如果成功调用第一个回调函数,如果失败调用第二个回调函数
            result.then(value => resolve(value), reason => reject(reason));
        } else { // 如果是普通值
            resolve(result); // 直接将普通值传递
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
  • 相关阅读:
    自动化测试的生命周期是什么?
    20220608-SCRFD-样本和计算重分配
    职场人该看懂的几个点
    uniapp打包:本应用使用HBuilderX 3.8.7或对应的cli版本编译,而手机端SDK版本是3.8.12.不匹配的版本可能造成应用异常
    【PCIE709-F】基于复旦微JFM7VX690T80 FPGA的全国产化8通道光纤双FMC接口数据处理平台
    react-router 源码及原理解析 v5版本
    前端文档网址
    这8个忠告会让你在2024过得更好
    解决QT信号在信号和槽连接前发出而导致槽函数未调用问题
    消息中间件概述
  • 原文地址:https://blog.csdn.net/m0_46612221/article/details/126177185