JS异步编程:手写Promise

571 阅读16分钟

注:

  1. 此文章仅为学习Promise的原理,有一些细节问题和边界处理没有判断,代码不可用于生产环境。如:浏览器内置的Promise使用微任务实现异步,这里用 setTimeout 宏任务实现异步。当Promise代码书写过程中嵌入 setTimeout 代码的时候,输出可能与浏览器不一样。这里没有完全模拟浏览器的微任务
  2. 完整代码-github。其中每一个commit都对应一个小标题,可以对照查看

初始结构

使用:

let p = new Promise((resolve, reject) => {
    resolve('OK');
});

p.then(value => {
    console.log(value);
}, reason=>{
    console.warn(reason);
})

基本结构:

//声明构造函数
function Promise(executor){
    
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){

}

resolvereject 结构

//声明构造函数
function Promise(executor){
    //resolve 函数
    function resolve(data){

    }
    //reject 函数
    function reject(data){

    }

    //同步调用『执行器函数』
    executor(resolve, reject);
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){

}

resolvereject 函数实现

resolvereject 函数执行后,做了两件事

  1. 修改对象的状态(promiseState)
  2. 设置对象的结果值(promiseResult)

所以,实例需要两个属性,存储状态和结果。然后在 resolvereject 函数中改变状态与结果值

function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
    }
    //reject 函数
    function reject(data){
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
    }

    //同步调用『执行器函数』
    executor(resolve, reject);
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){

}

throw 抛出错误改变状态

改变对象状态有三种方式:resolvereject,抛出异常

这里我们完善一下抛出异常时改变状态的逻辑

如下try catch方法:

//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
    }
    //reject 函数
    function reject(data){
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){

}

测试一下

let p = new Promise((resolve, reject) => {
            // resolve('OK');
            // reject("error");
            //抛出异常
            throw "error";
        });

        console.log(p);

image。png

[[]] 双括号表示这两个属性是浏览器规定的内置属性,我们没有办法通过js去直接操作

以上就是基本的结构,接下来处理细节问题

状态只能修改一次

状态只能修改一次,只能从 pending 转为 fulfilled 或者 reject

思路:在改变状态之前,判断一下状态是否被改过了,如果被改过了就不再进行操作

//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
    }
    //reject 函数
    function reject(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){

}

测试一下

let p = new Promise((resolve, reject) => {
    reject("error");
    resolve('OK');
});

console.log(p);

image。png

then 方法执行回调

then 中的两个回调函数执行,有他自己的条件,如果状态为 fulfilled ,执行第一个,如果是 rejected ,就执行第二个

注意此时仅仅只能运行同步修改状态的回调

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    //调用回调函数  PromiseState
    if(this.PromiseState === 'fulfilled'){
        onResolved(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onRejected(this.PromiseResult);
    }
}

测试一下,三种修改状态的方式,都可以正常运行

let p = new Promise((resolve, reject) => {
    // resolve('OK');
    // reject("Error");
    throw "ERROR";
});

p.then(value => {
    console.log(value);
}, reason=>{
    console.warn(reason);
})

异步任务 then 回调的执行

上面的代码仅仅支持同步代码,如果包裹一个异步操作,那么无法正常运行,例如下面:

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
        // reject("error");
    }, 1000);
});

p.then(value => {
    console.log(value);
}, reason=>{
    console.warn(reason);
});

console.log(p);

没有任何输出,这里是因为,如果同步执行代码,遇到异步操作,那么同步执行的代码运行到 then 一直是 pending 状态。所以没有任何反应。那么我们修改一下整体和 then 的逻辑。

  1. 在Promise构造函数中,添加 callback 属性,存放执行异步操作时 then 的回调函数
  2. then 方法中判断,如果执行器 executor 执行的是异步操作,那么状态应该为 pending ,那么此时就把回调函数暂存起来
  3. 在异步到时间,执行 resolvereject 的时候,再将响应的 callback 拿出来执行

代码如下:注意三个地方的callback的处理

//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //声明属性
    this.callback = {};
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //调用成功的回调函数
        if(self.callback.onResolved){
            self.callback.onResolved(data);
        }
    }
    //reject 函数
    function reject(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //执行回调
        if(self.callback.onRejected){
            self.callback.onRejected(data);
        }
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    //调用回调函数  PromiseState
    if(this.PromiseState === 'fulfilled'){
        onResolved(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onRejected(this.PromiseResult);
    }
    //判断 pending 状态
    if(this.PromiseState === 'pending'){
        //保存回调函数
        this.callback = {
            onResolved,
            onRejected
        }
    }
}

再执行一下上面的异步测试操作: 正常

image。png

image。png

指定多个回调

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve('OK');
        reject('No');
    }, 1000);
});

p.then(value => {
    console.log(value);
}, reason=>{
    console.warn(reason);
});

p.then(value => {
    alert(value);
}, reason=>{
    alert(reason);
});

如果像上面这样,仅仅会 alert ,并没有打印,原因很多简单,因为第二次执行 then ,会把第一次存的 callback 覆盖,所以只有最后一次 then 有效。

所以我们用一种新的方法来解决这个问题,当遇到 then 的时候,将两个回调函数存到一个数组里,等到异步 resolve 的时候,从数组中拿出存的回调,依次执行

代码修改如下:

  1. callback 声明为一个数组
  2. resolve 或者 reject 的时候,从数组总拿出回调函数执行
  3. then 的时候,将回调函数存在 callback 数组中
//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //声明属性
    this.callbacks = [];
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //调用成功的回调函数
        self.callbacks.forEach(item => {
            item.onResolved(data);
        });
    }
    //reject 函数
    function reject(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //执行失败的回调
        self.callbacks.forEach(item => {
            item.onRejected(data);
        });
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    //调用回调函数  PromiseState
    if(this.PromiseState === 'fulfilled'){
        onResolved(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onRejected(this.PromiseResult);
    }
    //判断 pending 状态
    if(this.PromiseState === 'pending'){
        //保存回调函数
        this.callbacks.push({
            onResolved: onResolved,
            onRejected: onRejected
        });
    }
}

同步修改状态 then 方法返回结果(then链的实现)

then 方法返回结果有以下规则:

then 方法返回结果是由他指定的回调函数的返回结果决定的

  • 如果返回一个非Promise类型的数据,then方法返回的就是一个成功状态的Promise,返回值就是return的值
  • 如果返回了一个Promise类型的数据,then方法返回的的结果和状态就由返回的这个Promise决定
  • 如果抛出错误,就返回一个失败的Promise,值为错误

测试代码:

//实例化对象
let p = new Promise((resolve, reject) => {
    resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
    console.log(value)
    //抛出异常测试
    //throw "FAIL";
}, reason=>{
    console.warn(reason);
});
console.log(res);

下面实现这个流程

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    //1. 返回的是Promise类型的数据
    return new Promise((resolve, reject) => {
        //调用回调函数  PromiseState
        if(this.PromiseState === 'fulfilled'){
            try{4. 处理抛出异常的情况
                //2. 获取回调函数的执行结果
                let result = onResolved(this.PromiseResult);
                //3. 判断
                if(result instanceof Promise){
                    //3.1如果是 Promise 类型的对象
                    //返回的结果就是返回的这个Promise(result)的值和状态
                    //返回的Promise的值和状态(result)又由这个result的then来决定,then中的回调代表最后这个Promise到底是什么状态.
                    result.then(v => {
                        resolve(v);
                    }, r=>{
                        reject(r);
                    })
                }else{
                    //3.2如果不是Promise类型
                    //结果的对象状态为『成功』,值就是then回调函数执行的结果
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }
        }
        if(this.PromiseState === 'rejected'){
            try{
                let result = onRejected(this.PromiseResult);
                if(result instanceof Promise){
                    result.then(v => {
                        resolve(v);
                    }, r=>{
                        reject(r);
                    })
                }else{
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }
        }
        //判断 pending 状态
        if(this.PromiseState === 'pending'){
            //保存回调函数
            this.callbacks.push({
                onResolved: onResolved,
                onRejected: onRejected
            });
        }
    })
}

可以看上面1,2,3三个步骤

  1. 首先 then 返回的是 Promise 类型的数据,所以 return new Promise
  2. 首先获取 then 回调函数的执行结果 result
  3. result 是什么值
    • 3.1 如果 resultPromise 。那么最后 then 返回的结果就由result的结果来决定。而 result 的结果和值是通过 .then 来获知的,所以获取结果后,再返回给最外面的Promise
    • 3.2 如果不是 Promise 类型,那么回调函数的结果,就是结果
  4. 注意不要忘记处理抛出异常的情况

同样,当状态为 rejected 的时候执行一样的逻辑

image。png 接下来测试一下几种 then 链的情况

let p = new Promise((resolve, reject) => {
    resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
    console.log(value)
    return 'okokok'
}, reason=>{
    console.warn(reason);
});
console.log(res);

image。png

let p = new Promise((resolve, reject) => {
    resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
    console.log()
    return new Promise((resolve,reject)=>{
        resolve('r test')
    })
}, reason=>{
    console.warn(reason);
});
console.log(res);

image。png

let p = new Promise((resolve, reject) => {
    resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
    //抛出异常
    throw "FAIL";
}, reason=>{
    console.warn(reason);
});
console.log(res);

image。png

在异步状态下修改 then 方法的返回结果(异步执行时的 then 链)

上面then链的实现仅仅只能在Promise同步修改状态时可用。下面实现在异步操作下修改 then 方法的返回结果。

当出现异步操作时,进入 then 函数的时候,Promise处于 pending 状态,所以在 pending 的时候,存储回调函数时,也要进行同样的 then 链的处理。

因为对then链的处理都是一样的逻辑,仅仅是执行的函数不同,所以可以将逻辑抽离出来,封装为一个函数。进行代码的优化

最后还要注意 this 的指向问题

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    //1. 注意this指向问题
    const self = this;
    return new Promise((resolve, reject) => {
        //2. 封装函数,then链的处理机制
        function callback(type){
            try{
                //获取回调函数的执行结果
                let result = type(self.PromiseResult);
                //判断
                if(result instanceof Promise){
                    //如果是 Promise 类型的对象
                    result.then(v => {
                        resolve(v);
                    }, r=>{
                        reject(r);
                    })
                }else{
                    //结果的对象状态为『成功』
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }
        }
        //调用回调函数  PromiseState
        //3. 不同的状态进行不同的then链处理 
        if(this.PromiseState === 'fulfilled'){
            callback(onResolved);
        }
        if(this.PromiseState === 'rejected'){
            callback(onRejected);
        }
        //判断 pending 状态
        if(this.PromiseState === 'pending'){
            //保存回调函数
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){
                    callback(onRejected);
                }
            });
        }
    })
}

几个修改的地方如下:

  1. 注意 this 的指向问题, type(self.PromiseResult) 传入的状态是原来的Promise的状态
  2. 封装函数,传入需要执行的函数
  3. 不同状态下进行不同的 then 链的处理

测试一下不同的情况,注意1s之后在查看打印,因为1s之后回调才执行完毕:

        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
                // reject('Error');
            }, 1000);
        });

        //执行 then 方法
        const res = p.then(value => {
            console.log(value);
            return value
        }, reason=>{
            console.warn(reason);
        });

        console.log(res);

image。png

        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
                // reject('Error');
            }, 1000);
        });

        //执行 then 方法
        const res = p.then(value => {
            console.log(value);
            return new Promise((resolve, reject) => {
                resolve('new p')
            })
        }, reason=>{
            console.warn(reason);
        });

        console.log(res);

image。png

let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
                // reject('Error');
            }, 1000);
        });

        //执行 then 方法
        const res = p.then(value => {
            console.log(value);
            throw 'errerr'
        }, reason=>{
            console.warn(reason);
        });

        console.log(res);

image。png

reject 状态也是一样,不再进行测试

catch 方法

catchthen 的语法糖,所以

//添加 catch 方法
Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}

then 链穿透

then链的穿透机制如下,如果不传 then 的回调函数,(或者回调函数不是函数类型)那么处理将会继续延伸到下一个 then

image。png 看一下我们刚才的代码,当传入一个 undefined 的时候,无法运行,那么将会报错

所以我们判断then传入的值即可

异常穿透

完善异常穿透机制:

Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    //判断回调函数参数
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    ...//剩余代码先不写
}

image。png

测试:

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('OK');
        // resolve('OK');
    }, 1000);
});

//异常穿透
p.then()
.then(value=>{
    console.log(222);
}).then(value => {
    console.log(333);
}).catch(reason => {
    console.warn(reason);
});

image。png

或者中途出现错误

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // reject('OK');
        resolve('OK');
    }, 1000);
});

//异常穿透
p.then()
.then(value=>{
    throw 'ok1'
    console.log(222);
}).then(value => {
    console.log(333);
}).catch(reason => {
    console.warn(reason);
});

image。png

值传递

延伸一下,不光错误可以传递,成功的回调也可以传递。如果第一个回调函数不传,会把值继续传到下一个 then 中的第一个回调处理。实现也很简单,直接将 onResolve 函数改为传入什么,返回什么的函数即可

Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    //判断回调函数参数
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
    }
}

then 方法回调的异步执行

这里有一个细节, then 方法中的回调函数是异步执行的

then 方法的回调在内置的Promise中是异步执行的微任务,等所有同步代码执行完毕后,才会执行then中的异步微任务回调。这里我们用 setTimeout 来模拟实现

参考:手写Promise

由于原生的 Promise 是V8引擎提供的微任务,我们无法还原V8引擎的实现,所以这里使用 setTimeout 模拟异步,所以原生的是微任务,这里是宏任务。

Promise A+ 规范3.1 中也提到了:这可以通过“宏任务”机制(例如setTimeout或setImmediate)或“微任务”机制(例如MutatonObserver或)来实现process。nextTick。

如果想实现 promise 的微任务,可以 mutationObserver 替代 seiTimeout 来实现微任务。 有小伙伴说可以使用 queueMicrotask 实现微任务,我也查阅了一些资料,是可以的。不过 queueMicrotask 兼容性不是很好,IE 下完全不支持。据我所知 queueMicrotask 的 polyfill 是基于 promise 实现的,如果不支持 promise 会转成 setTimeout。 总的来说,queueMicrotask 和 mutationObserver 都可以实现微任务机制,不过更建议有执念的小伙伴用 mutationObserver 实现一下,没有执念的小伙伴了解 promise 的微任务机制就好了~

如下面的代码输出

let p1 = new Promise((resolve, reject) => {
    reject('OK');
    console.log(111);
});

p1.then(value => {
    console.log(222);
}, reason => {
    console.log(444);
});

console.log(333);

我们来测试一下如果不进行异步回调操作,用我们自己写的代码测试一下输出:

image。png 直接按照顺序输出

但是如果是浏览器原生的Promise输出,结果应该为:

image。png

所以then中的回调应该是异步的,所以要在执行回调的时候,加上 setTimeout

以下是Promise的完整的代码(注意加上 setTimeout 的部分:

//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //声明属性
    this.callbacks = [];
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //调用成功的回调函数
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved(data);
            });
        });
    }
    //reject 函数
    function reject(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //执行失败的回调
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected(data);
            });
        });
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    //判断回调函数参数
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
        //value => { return value};
    }
    return new Promise((resolve, reject) => {
        //封装函数
        function callback(type){
            try{
                //获取回调函数的执行结果
                let result = type(self.PromiseResult);
                //判断
                if(result instanceof Promise){
                    //如果是 Promise 类型的对象
                    result.then(v => {
                        resolve(v);
                    }, r=>{
                        reject(r);
                    })
                }else{
                    //结果的对象状态为『成功』
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }
        }
        //调用回调函数  PromiseState
        if(this.PromiseState === 'fulfilled'){
            setTimeout(() => {
                callback(onResolved);
            });
        }
        if(this.PromiseState === 'rejected'){
            setTimeout(() => {
                callback(onRejected);
            });
        }
        //判断 pending 状态
        if(this.PromiseState === 'pending'){
            //保存回调函数
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){
                    callback(onRejected);
                }
            });
        }
    })
}

//添加 catch 方法
Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}

其他方法

Promise.resolve

//添加 resolve 方法
Promise.resolve = function(value){
    //返回promise对象
    return new Promise((resolve, reject) => {
        if(value instanceof Promise){
            value.then(v=>{
                resolve(v);
            }, r=>{
                reject(r);
            })
        }else{
            //状态设置为成功
            resolve(value);
        }
    });
}

Promise.reject

//添加 reject 方法
Promise.reject = function(reason){
    return new Promise((resolve, reject)=>{
        reject(reason);
    });
}

Promise.all

//添加 all 方法
Promise.all = function(promises){
    //返回结果为promise对象
    return new Promise((resolve, reject) => {
        //声明变量
        let count = 0;
        let arr = [];
        //遍历
        for(let i=0;i<promises.length;i++){
            //
            promises[i].then(v => {
                //得知对象的状态是成功
                //每个promise对象 都成功
                count++;
                //将当前promise对象成功的结果 存入到数组中
                arr[i] = v;
                //判断
                if(count === promises.length){
                    //修改状态
                    resolve(arr);
                }
            }, r => {
                reject(r);
            });
        }
    });
}

Promise.race

//添加 race 方法
Promise.race = function(promises){
    return new Promise((resolve, reject) => {
        for(let i=0;i<promises.length;i++){
            promises[i].then(v => {
                //修改返回对象的状态为 『成功』
                resolve(v);
            },r=>{
                //修改返回对象的状态为 『失败』
                reject(r);
            })
        }
    });
}

class版本封装

以上代码为构造函数版本,用最新的class封装如下:



class Promise{
    //构造方法
    constructor(executor){
        //添加属性
        this.PromiseState = 'pending';
        this.PromiseResult = null;
        //声明属性
        this.callbacks = [];
        //保存实例对象的 this 的值
        const self = this;// self _this that
        //resolve 函数
        function resolve(data){
            //判断状态
            if(self.PromiseState !== 'pending') return;
            //1. 修改对象的状态 (promiseState)
            self.PromiseState = 'fulfilled';// resolved
            //2. 设置对象结果值 (promiseResult)
            self.PromiseResult = data;
            //调用成功的回调函数
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onResolved(data);
                });
            });
        }
        //reject 函数
        function reject(data){
            //判断状态
            if(self.PromiseState !== 'pending') return;
            //1. 修改对象的状态 (promiseState)
            self.PromiseState = 'rejected';// 
            //2. 设置对象结果值 (promiseResult)
            self.PromiseResult = data;
            //执行失败的回调
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onRejected(data);
                });
            });
        }
        try{
            //同步调用『执行器函数』
            executor(resolve, reject);
        }catch(e){
            //修改 promise 对象状态为『失败』
            reject(e);
        }
    }

    //then 方法封装
    then(onResolved,onRejected){
        const self = this;
        //判断回调函数参数
        if(typeof onRejected !== 'function'){
            onRejected = reason => {
                throw reason;
            }
        }
        if(typeof onResolved !== 'function'){
            onResolved = value => value;
            //value => { return value};
        }
        return new Promise((resolve, reject) => {
            //封装函数
            function callback(type){
                try{
                    //获取回调函数的执行结果
                    let result = type(self.PromiseResult);
                    //判断
                    if(result instanceof Promise){
                        //如果是 Promise 类型的对象
                        result.then(v => {
                            resolve(v);
                        }, r=>{
                            reject(r);
                        })
                    }else{
                        //结果的对象状态为『成功』
                        resolve(result);
                    }
                }catch(e){
                    reject(e);
                }
            }
            //调用回调函数  PromiseState
            if(this.PromiseState === 'fulfilled'){
                setTimeout(() => {
                    callback(onResolved);
                });
            }
            if(this.PromiseState === 'rejected'){
                setTimeout(() => {
                    callback(onRejected);
                });
            }
            //判断 pending 状态
            if(this.PromiseState === 'pending'){
                //保存回调函数
                this.callbacks.push({
                    onResolved: function(){
                        callback(onResolved);
                    },
                    onRejected: function(){
                        callback(onRejected);
                    }
                });
            }
        })
    }

    //catch 方法
    catch(onRejected){
        return this.then(undefined, onRejected);
    }

    //添加 resolve 方法
    static resolve(value){
        //返回promise对象
        return new Promise((resolve, reject) => {
            if(value instanceof Promise){
                value.then(v=>{
                    resolve(v);
                }, r=>{
                    reject(r);
                })
            }else{
                //状态设置为成功
                resolve(value);
            }
        });
    }

    //添加 reject 方法
    static reject(reason){
        return new Promise((resolve, reject)=>{
            reject(reason);
        });
    }

    //添加 all 方法
    static all(promises){
        //返回结果为promise对象
        return new Promise((resolve, reject) => {
            //声明变量
            let count = 0;
            let arr = [];
            //遍历
            for(let i=0;i<promises.length;i++){
                //
                promises[i].then(v => {
                    //得知对象的状态是成功
                    //每个promise对象 都成功
                    count++;
                    //将当前promise对象成功的结果 存入到数组中
                    arr[i] = v;
                    //判断
                    if(count === promises.length){
                        //修改状态
                        resolve(arr);
                    }
                }, r => {
                    reject(r);
                });
            }
        });
    }

    //添加 race 方法
    static race (promises){
        return new Promise((resolve, reject) => {
            for(let i=0;i<promises.length;i++){
                promises[i].then(v => {
                    //修改返回对象的状态为 『成功』
                    resolve(v);
                },r=>{
                    //修改返回对象的状态为 『失败』
                    reject(r);
                })
            }
        });
    }
}