首页 > 技术文章 > 一步步手写Promise

GiornoGiovanna 2021-11-30 18:20 原文

Promise

promise介绍

promise是ES6规范,是JavaScript中用于解决异步编程的新方案,异步操作有:node.js下的文件操作,数据库操作,AJAX,定时器。从语法上来说Promise是一个构造函数,从功能上来说promise对象用来封装一个异步操作并可以获取其成功以及失败的结果。

在过去的方案中,解决异步编程是使用回调函数,当一个回调函数返回值需要作为下一个回调函数的参数传入时,容易造成回调地狱问题。回调地狱不便于阅读,也不便于异常处理。而Promise支持链式调用,可以解决回调地狱问题。

promise示例

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #btn {
            width: 40;
            height: 20;
            border-radius: 3px;
            color: rgb(189, 164, 164);
            font-size: 16px;
        }
    </style>
</head>

<body>
    <h3>抽奖游戏</h3>
    <button id="btn">抽奖</button>
</body>
<script>
    function rand(m, n) {
        return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
    }
    const btn = document.querySelector('#btn')
    btn.addEventListener('click', function () {
        const p = new Promise((resolve, reject) => {
            setTimeout(() => {
                let n = rand(1, 100)
                if (n <= 30) {
                    resolve(n)
                } else {
                    reject(n)
                }
            }, 1000)
        })
        p.then((result) => {
            alert('中奖了,中奖号码为' + result)
        }).catch((err) => {
            alert('没有中奖,号码为' + err)
        });

    })
</script>

</html>

then回调函数输出promise成功的结果,result接收resolve中的参数n。catch回调函数输出promise失败的结果,error接收reject中的参数n

const p = new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.response)
                } else {
                    reject(xhr.status)
                }
            }
        }
    })
    p.then((result) => {
        console.log(result)
    }, (error) => {
        console.log(error)
    })
    console.log(p)

 

then中的第一个回调函数接收promise成功的结果,第二个回调函数接收promise失败的结果,回调函数中的参数分别接收resovle和reject中的参数并输出。

Promise状态

一个 Promise 必然处于以下几种状态之一:

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

Promise参数

Promise返回的也是一个Promise对象。返回的参数包括:

类型:Promise

Promise的状态:已兑现或者已拒绝

Promise的结果:如果状态已经兑现,这个结果传入resolve的参数中。如果状态已经拒绝,那么这个结果就传入reject的参数中。

fufilled

 

rejected

 Promise工作流程

 

 

PromiseAPI

Promise executor函数

Promise构造函数 : Promise (excutor) {}
(1) executor函数 : 执行器 (resolve, reject) => {}
(2) resolve函数 : 内部定义成功时我们调用的函数 value => {}
(3) reject函数 : 内部定义失败时我们调用的函数 reason => {}

promise构造函数是同步执行的,then方法是异步执行的。

例如:

 new Promise(resolve => {
        console.log(1);
        resolve(3);
    }).then(num => {
        console.log(num);
    });
    console.log(2);

 

 

构建Promise对象时,需要传入一个executor函数,主要业务流程都在executor函数中执行.

Promise构造函数执行时立即调用executor函数,resolve和reject两个函数作为参数传递给executor,resolve和reject函数被调用时,分别将promise的状态改为fulfilled(完成)或者rejected(失败).一旦状态改变,就不会再变。在executor函数内执行的resolve或reject函数是executor函数传递进来的两个参数,传参和命名函数的名称要一致。

 

Promise.prototype.then方法 : (onResolved, onRejected) => {}

(1) onResolved函数 : 成功的回调函数 (value) => {}

(2) onRejected函数 : 失败的回调函数 (reason) => {}

then方法指定用于得到成功 value的成功回调和用于得到失败 reason的失败回调,返回一个新的promse对象

 

Promise.prototype.catch方法 : (onRejected) => {}

(1) onRejected函数 : 失败的回调函数 (reason) => {},catch方法只能指定失败的回调。

 

Promise方法

Promise.resolve方法 : (value) => {}

如果传入resolve方法为非promise类型的对象,则返回的结果为成功的promise对象。

 let p1 = Promise.resolve(521);
    console.log(p1)

 

 

 如果传入resolve的方法为promise类型的对象,则传入的promise的结果决定了resolve的结果

参数结果是成功的promise

 let p = Promise.resolve(new Promise((resolve, reject) => {
        resolve('123456')
    }))
    console.log(p)

 

 

 参数结果是失败的promise

let p = Promise.resolve(new Promise((resolve, reject) => {
        reject('未知错误')
    }))
    console.log(p)
    p.catch((error) => {//使用catch捕获错误

    })

 

Promise.reject方法 : (reason) => {}

(1) reason: 失败的原因
reject方法返回一个失败的promise对象,不论传入什么值,都是失败的状态。

 let p = Promise.reject('状态时失败的promis')
    console.log(p)
    p.catch((error) => {})

 

 

 Promise.all方法 : (promises) => {}

(1) promises: 包含 n个 promise的数组
all方法返回一个新的 promise, 只有所有的 promise都成功才成功 ,并返回所有成功的结果。 只要有一个失败了就直接失败,并返回失败的结果

全部成功的promise

let p1 = Promise.resolve('成功的promise1')
    let p2 = Promise.resolve('成功的promise2')
    let p3 = Promise.resolve('成功的promise3')
    let p4 = Promise.all([p1, p2, p3])
    console.log(p4)

 

 

 

 含有失败的promise

let p1 = Promise.resolve('成功的promise1')
    let p2 = Promise.resolve('成功的promise2')
    let p3 = new Promise((resolve, reject) => {
        reject('状态为失败的promise')
    })
    let p4 = Promise.all([p1, p2, p3])
    console.log(p4)
    p4.catch((error) => {

    })

Promise.race方法 : (promises) => {}

(1) promises: 包含 n个 promise的数组
race()方法返回一个新的 promise, 第一个完成的 promise的结果状态就是最终的结果状态

let p1 = Promise.resolve('成功的promise1')
    let p2 = Promise.resolve('成功的promise2')
    let p3 = new Promise((resolve, reject) => {
        reject('状态为失败的promise')
    })
    let p4 = Promise.race([p1, p2, p3])
    console.log(p4)
    p4.catch((error) => {

    })

 

 

 可以看到,即使含有错误的promise,但是第一个promise率先执行。所以返回第一个promise成功的结果。

Promise细节

Promise改变状态

promise状态的改变可以使用以下几种方法

(1) resolve(value): 如果当前是 pending就会变为 resolved
(2) reject(reason): 如果当前是 pending就会变为 rejected
(3) 抛出异常 : 如果当前是 pending就会变为 rejected

resolve改变状态

let p1 = new Promise((resolve, reject) => {
        resolve(123)
    })
    console.log(p1)

 

 

 

 reject改变状态

let p1 = new Promise((resolve, reject) => {
        reject(123)
    })
    console.log(p1)
    p1.catch((error) => {})

 

 throw改变状态

 let p1 = new Promise((resolve, reject) => {
        throw (123)
    })
    console.log(p1)
    p1.catch((error) => {
        console.log(error)
    })

Promise指定多个成功/失败的回调

promise可以指定多个成功的或者失败的promise回调函数,并且这些回调函数都会被执行。

指定多个成功的promise回调

let p = new Promise((resolve, reject) => {
        resolve('成功的promise')
    })
    p.then((result) => {
        console.log(result)
    })
    p.then((result) => {
        console.log(result)
    })

 

 

 

 

指定多个失败的promise回调

let p = new Promise((resolve, reject) => {
        reject('状态失效的promise')
    })
    p.then(() => {}, (error) => {
        console.log(error)
    })
    p.then(() => {}, (error) => {
        console.log(error)
    })

Promise状态的改变和回调函数的指定

(1) promise状态改变和回调函数的指定顺序是:正常情况下是先指定回调再改变状态 , 但也可以先改状态再指定回调。改变状态就是执行resolve,reject,throw。指定回调就是执行then方法里面的回调函数
(2) 先改状态再指定回调 
① 在执行器中直接调用 resolve()/reject(),就是同步执行resolve()/reject(),再执行then方法

let p = new Promise((resolve, reject) => {
        resolve('先改变状态,再指定回调')
    })
    p.then((result) => {
        console.log(result)
    }).catch((err) => {

    });
    console.log(p)

(3)先指定回调,再改变状态

let p = new Promise((resolve, reject) => {
        setTimeout(function () {
            resolve('先指定回调再改变状态')
        }, 3000)
    })
    p.then((result) => {
        console.log(result)
    }).catch((err) => {

    });
    console.log(p)

(4) 获取数据的顺序
① 如果先指定的回调 , 那当状态发生改变时 , 回调函数就会调用 , 得到数据
② 如果先改变的状态 , 那当指定回调时 , 回调函数就会调用 , 得到数据

 

promise.then()返回的新 promise的结果

then方法会返回一个新的promise,新的promise的结果由函数回调函数的返回决定。

① 如果抛出异常 , 新 promise变为 rejected, reason为抛出的异常

let p = new Promise((resolve, reject) => {
        resolve('okay')
    })
    let result = p.then((result) => {
        throw ('错误')
    }, (err) => {})
    console.log(result)


② 如果返回的是非 promise的任意值 , 新 promise变为 resolved, value为返回的值

let p = new Promise((resolve, reject) => {
        resolve('okay')
    })
    let result = p.then((result) => {
        return 100
    }, (err) => {})
    console.log(result)

 

③ 如果返回的是另一个新 promise, 此 promise的结果就会成为新 promise的结果

let p = new Promise((resolve, reject) => {
        resolve('okay')
    })
    let result = p.then((result) => {
        return new Promise((resolve, reject) => {
            resolve('HTML')
        })
    }, (err) => {})
    console.log(result)

 

 

 

 

 Promise串联多个操作任务

promise可以串联多个操作,因为欸then方法返回的也是一个promise对象

let p = new Promise((resolve, reject) => {
        resolve('success')
    })
    p.then((result) => {
        console.log(result) //这里的结果是第一个promise状态改变的结果
        return new Promise((resolve, reject) => {
            resolve('SUCCESS')
        })
    }, (error) => {

    }).then((result) => {
        console.log(result) //此处结果是第二一个promise对象改变的结果。
    }).then((result) => {
        console.log(result) //上一个then返回的也是一个promise对象,但是promise对象状态为指定,没有写返回值,所以是undefined
    })

 

 

 Promise异常穿透

promise使用then进行链式调用时,可以在最后指定失败的回调。

let p = new Promise((resolve, reject) => {
        // resolve('success1')
        reject("错误")
    })
    p.then((result) => {
        console.log(result)
        console.log('success2')
    }).then((result) => {
        console.log('success3')
    }).then((result) => {
        console.log('success4')
    }).then((result) => {
        console.log('success5')
    }).catch((err) => {
        console.log(err)
    });

 

 

Promise终止链式调用

promise终止链式调用有且只有一种方法:返回Pending状态的Promise,这样promise才会不继续执行从而继续返回一个新的promise对象

 let p = new Promise((resolve, reject) => {
        resolve('success1')
        // reject("错误")
    })
    p.then((result) => {
        console.log(result)
        console.log('success2')
    }).then((result) => {
        console.log('success3')
        return new Promise(() => {})
    }).then((result) => {
        console.log('success4')
    }).then((result) => {
        console.log('success5')
    }).catch((err) => {
        console.log(err)
    });

 

Promise自定义封装

Function版Promise

1.搭建基本结构

function Promise(executor){

}

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

}

 

1.为Promise添加状态与属性,添加resolve方法与reject方法。

2.调用resolve方法与reject方法前对当前状态进行判断,当前状态处于pending才能通过resovle方法与reject方法Promise改变状态与属性。

3.为executor添加try、catch语句,检测ececutor语句块的异常并并捕获。

 


//声明构造函数
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){

}

1.定义then方法。调用then方法时,根据Promise的状态调用成功时的回调或失败时的回调,把成功与失败时的PromiseResult分别传输给then中的成功的回调函数与失败的回调函数作为参数输出。

<script>
        //实例化对象
        let p = new Promise((resolve, reject) => {
            resolve('OK');
            // reject("Error");
            // throw "ERROR";
        });

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

 

//声明构造函数
function Promise(executor){
  //篇幅有限删除了这部分重复代码,仅展示所需方法的代码
}

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

 

1.resolve,reject方法是异步执行时,同步执行到then,Promise处于pending状态,为then添加pending状态的判断。把onResolved,onRejected保存到构造函数Promise中供resolve,reject方法调用。

2.当异步的resolve,reject方法执行完毕后改变状态,分别调用onResolved,onRejected方法执行then方法中的回调函数。

<script>
        //实例化对象
        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);
    </script>

 

//声明构造函数
function Promise(executor) {
    //添加属性
    this.PromiseState = 'pending'
    this.PromiseResult = null
    //声明属性
    this.callback = {}
    //保存实例对象的 this 的值
    const self = this
    //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)
        }
    }
}

//添加 then 方法
Promise.prototype.then = function (onResolved, onRejected) {
  //篇幅有限删除了这部分代码
if (this.PromiseState === 'pending') { //保存回调函数 this.callback = { onResolved: onResolved, onRejected: onRejected, } } }

 

1.当一个Promise方法中的resolve,reject方法是异步,且Promise指定多个回调时,后面保存的回调函数会把前面保存的回调函数覆盖掉导致只有最后一个回调函数执行。

2.改进方法:在pending状态下,把回调函数的保存形式改为压入数组中保存,这样promise指定多少个回调函数,数组中就有多少个回调函数。每个指定的回调函数都能执行。

<script>
        //实例化对象
        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);
        });

        console.log(p);
//声明构造函数
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)
        })
    }
}

//添加 then 方法
Promise.prototype.then = function (onResolved, onRejected) {//判断 pending 状态
    //1.以为数组的形式保存回调函数,如果有多个处于pending状态的then方法,这里就会把相同数量的回调函数以对象形式压入数组中
    //2.这样避免了以对象形式保存,第二个pending状态的then把第一个pending状态下的then的回调函数覆盖
    //3.这里的p.then是同步执行的
    if (this.PromiseState === 'pending') {
        //保存回调函数
        this.callbacks.push({
            onResolved: onResolved,
            onRejected: onRejected,
        })
    }
}

 

1.同步的resolve,reject下模拟内置的then方法返回Promise对象,这个返回的Promise对象的状态由回调函数的返回决定。

2.在then方法中对fulfillde状态和rejected状态中分别调用onResolve,onReject这两个回调函数。并接收这两个回调函数的返回值,对返回值进行判断。如果返回的是一个Promise对象,那么then方法的返回Promise状态就由这个Promise决定,如果返回的是一个非Promise对象,那么状态就为成功。如果抛出错误,状态就为reject。

3.对Promise状态的代码重复使用了,封装成为函数。

<script>
        //实例化对象
        let p = new Promise((resolve, reject) => {
            resolve('OK');
        });
        //执行 then 方法
        const res = p.then(value => {
            console.log(value)
            return 'hello'
            // throw "FAIL";
        }, reason => {
            console.warn(reason);
        });
        console.log(p)
        console.log('----------------------')
        console.log(res);
    </script>

 

//声明构造函数
function Promise(executor) {
  //篇幅有限删除无关代码
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    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'){
            callback(onResolved);
        }
        if(this.PromiseState === 'rejected'){
            callback(onRejected);
        }
    })
}

 

异步任务下then方法返回的实现,在异步的resolve,reject中,Promise一直处于pending状态,需要对pending状态添加判断,判断then返回的Promise的状态,逻辑实现同一步,直接调用封装的函数

<script>
        //实例化对象
        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('OK');
                // reject("Error");
            }, 1000)
        });

        //执行 then 方法
        const res = p.then(value => {
            console.log(value)
            return 'oh Yeah';
            // throw 'error';
        }, reason => {
            console.warn(reason);
            // throw 'error';
        });
        console.log(p)
        console.log(res);
    </script>

 

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    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'){
            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.添加catch方法用于调用reject。

2.如果异步状态下调用then方法而不添加参数,那么pending状态下传入Promise.prototype.then = function(onResolved, onRejected),then方法中的两个参数是Undefined,会报错,所以需要对传入的参数进行判断

 <script>
        //实例化对象
        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);
        });


    </script>
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};
    }
}

 

1.添加resolve方法,resolve方法返回的也是一个Promise对象,并且返回的Promise状态由resolve返回的回调决定。

 <script>
        const p = Promise.resolve('OK');
        const p2 = Promise.resolve(new Promise((resolve, reject) => {
            // resolve('Success');
            reject("error");
        }));
        const p3 = Promise.resolve(Promise.resolve('Oh Yeah'));

        console.log(p3);
    </script>

 

//添加 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);
        }
    });
}

 

1.添加reject方法,reject方法返回的永远是失败的Promise

<script>
        //Promise.reject
        const p = Promise.reject('Error');
        const p2 = Promise.reject(new Promise((resolve, reject) => {
            resolve('OK');
        }));

        console.log(p);
        console.log(p2);
    </script>
//添加 reject 方法
Promise.reject = function(reason){
    return new Promise((resolve, reject)=>{
        reject(reason);
    });
}

 

1.添加all方法

 <script>
        let p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('OK');
            }, 1000)
        })
        let p2 = Promise.reject('Success');
        let p3 = Promise.resolve('Oh Yeah');

        //调用 all 方法
        let result = Promise.all([p1, p2, p3]);

        console.log(result);
    </script>
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);
            });
        }
    });
}

1.添加race方法

 <script>
        let p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('OK');
            });
        });
        let p2 = Promise.reject('Success');
        let p3 = Promise.resolve('Oh Yeah');

        //调用 race 方法
        let result = Promise.race([p1, p2, p3]);

        console.log(result);
    </script>
//添加 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);
            })
        }
    });
}

 

把then方法修改为异步执行的promise,在内置的Promise中,then是异步执行的。

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

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

        console.log(333);
    </script>
//excepted output=111 333 //声明构造函数
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);
            });
        });
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;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);
            });
        }
    })
}

完整的Function版本Promise

//声明构造函数
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);
}

//添加 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);
        }
    });
}

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

//添加 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);
            });
        }
    });
}

//添加 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版的Promise

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);
                })
            }
        });
    }
}   

async与await

async 函数

async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。asyncawait关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise

async函数可能包含0个或者多个await表达式。await表达式会暂停整个async函数的执行进程并出让其控制权,只有当其等待的基于promise的异步操作被兑现或被拒绝之后才会恢复进程。promise的解决值会被当作该await表达式的返回值.

async函数一定会返回一个promise对象。如果一个async函数的返回值看起来不是promise,那么它将会被隐式地包装在一个promise中。async函数返回的promise对象由async执行的返回值决定。

await表达式

await  操作符用于等待一个Promise 对象。它只能在异步函数 async function中使用。

await 右侧的表达式一般为promise 对象, 但也可以是其它的值,如果表达式是promise 对象, await 返回的是promise 成功的值,如果表达式是其它值, 直接将此值作为await 的返回值
 

await 表达式会暂停当前 async function执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function

若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出,若需要捕获异常,可以使用try,catch捕获异常。

另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。

Async 与await结合使用

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}
f1();

 

推荐阅读