ES6-Promise使用与原理分析+手写

前言

1、Promise是什么

1.1、理解

  1. 抽象表达:
    1. Promise是一门新的技术(ES6规范)
    2. Promise是JS中进行异步编程的新解决方案

备注:旧方案是单纯的使用回调函数

  1. 具体表达:
    1. 从语法上来说:Promise是一个构造函数
    2. 从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

1.2、promise的基本状态改变

  1. pending变为resolved
  2. pending变为rejected

说明:只有这两种,且一个promise对象只能改变一次状态。无论变为成功还是失败,都会有一个结果数据。

  • 成功的结果数据一般称为value,失败的结果数据一般称为reason

1.3、promise的基本流程

在这里插入图片描述

2、为什么使用Promise

2.1、指定回调函数的方法更加灵活

  1. 旧的:必须再启动异步任务前指定
  2. promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以再异步任务结束后指定/多个)

2.2、支持链式调用,可以解决回调地狱问题

  1. 回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
  2. 回调地狱的缺点
    1. 不便于阅读
    2. 不便于一场处理

3、如何使用promise

如下-.-,查看API

API

1、构造函数

Promise构造函数:Promise (executor){}

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

说明:executor会在Promise内部立即同步调用,异步操作在执行器中执行

1.1、代码

<script>
    let pms = new Promise((resolve,reject) => {
        // 成功 promise的value为'aaa' 同步调用
        resolve('aaa')
    })
	console.log(pms)
</script>

1.2、结果

在这里插入图片描述

2、Promise.prototype.then

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

  1. onResolved函数:成功的回调函数 (value) => {}
  2. onRejected函数:失败的回调函数 (reason) => {}

说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调。返回一个新的Promise对象

2.1、代码

<script>
    let pms1 = new Promise((resolve,reject) => {
        // 成功 promise的value为'aaa'
        resolve('aaa')
    })

    let pms2 = new Promise((resolve,reject) => {
        // 失败 promise的value为'bbb'
        reject('bbb')
    })

    let pms1Then = pms1.then(resolve => {
        // pms1成功了,会走这个
        console.log("pms1 resolve",resolve)
        return resolve // return的值,作为pms2Then(promise对象)的result值。如果没有return,则默认undefined
    },reject => {
        console.log("pms1 reject",reject)
    })

    let pms2Then = pms2.then(resolve => {
        console.log("pms2 resolve",resolve)
    },reject => {
        // pms2失败了,会走这个
        console.log("pms2 reject",reject)
        return reject // return的值,作为pms2Then(promise对象)的result值
    })

    console.log("pms1Then",pms1Then)
    console.log("pms2Then",pms2Then)

</script>

2.2、结果

在这里插入图片描述

3、Promise.prototype.catch

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

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

说明:它是 Promise.prototype.then(undefined, onRejected) 的快捷方式

3.1、代码

<script>
    let pms1 = new Promise((resolve,reject) => {
        // 成功 promise的value为'aaa'
        resolve('aaa')
    })

    let pms2 = new Promise((resolve,reject) => {
        // 失败 promise的value为'bbb'
        reject('bbb')
    })

    let pms1Then = pms1.then(resolve => {
        // pms1成功了,会走这个
        console.log("pms1 resolve",resolve)
        return resolve
    },reject => {
        console.log("pms1 reject",reject)
    })

    let pms2Catch = pms2.catch((reject => {
        console.log("pm2 catch",reject)
        return reject
    }))

    console.log("pms1Then",pms1Then)
    console.log("pms2Catch",pms2Catch)

</script>

3.2、结果

在这里插入图片描述

4、Promise.prototype.finally

Promise.prototype.finally:() => {}

  1. 不管状态如何,都会执行的函数

说明:可以避免在 promise 的 then()catch() 处理程序中重复代码。

4.1、代码

<script>
    let pms1 = new Promise((resolve,reject) => {
        // 成功 promise的value为'aaa'
        resolve('aaa')
    })


    pms1.then(resolve => {
        console.log(resolve)
        // console.log("pms1回调方法执行完毕")
    },reject => {
        console.log(reject)
        // console.log("pms1回调方法执行完毕")
    })

    pms1.finally(()=>{
        console.log("pms1回调方法执行完毕")
    })

</script>

4.2、结果

在这里插入图片描述

5、Promise.resolve

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

  1. value:成功的数据或promise对象
  2. 如果参数是一个基本数据类型,则返回成功的promise对象,promise对象的值为传入的参数
  3. 如果参数是一个promise对象,则返回的promise对象的结果,是根据参数(promise对象)的结果来判断,如果参数promise对象成,则返回的promise对象的结果也是成功,反之失败。值也为参数promise对象返回的值

说明:返回一个成功/失败的promise对象

5.1、基本数据类型

5.1.1、代码
<script>
    let pms = Promise.resolve('aaa')
    console.log(pms)
</script>
5.1.2、结果

在这里插入图片描述

5.2、promise

5.2.1、代码
<script>
    let p1 = new Promise((resolve,reject) => {
        resolve('我成功啦')
    })
    let p2 = new Promise((resolve,reject) => {
        reject('我失败了')
    })
    let pms1 = Promise.resolve(p1)
    let pms2 = Promise.resolve(p2)
    console.log(pms1)
    console.log(pms2)
</script>
5.2.2、结果

在这里插入图片描述

6、Promise.reject

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

  1. reason:失败的原因
  2. 不管参数为基本数据类型还是promise对象,返回的promise对象始终为失败的

说明:返回一个失败的promise对象

6.1、基本数据类型与promise

6.1.1、代码
<script>
    let p2 = new Promise((resolve,reject) => {
        reject('我失败了')
    })
    let pms1 = Promise.reject('我成功啦')
    let pms2 = Promise.reject(p2)
    console.log(pms1)
    console.log(pms2)
</script>
6.1.2、结果

在这里插入图片描述

7、Promise.all

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

  1. promises:包含n个promise的数组
  2. 返回的新的promise值为所有promise成功的值组成的数组,数组顺序与参数数组中promise的顺序一致

说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了,就直接失败,返回的结果为失败的promise的结果

7.1、全部成功

7.1.1、代码
<script>
    let p1 = Promise.resolve('aaa')
    let p2 = Promise.resolve('bbb')
    let p3 = Promise.resolve('ccc')
    let pms1 = Promise.all([p1,p2,p3])
    console.log(pms1)
</script>
7.1.2、结果

在这里插入图片描述

7.2、有一个不成功

7.2.1、代码
<script>
    let p1 = Promise.reject('aaa') // 失败
    let p2 = Promise.resolve('bbb')
    let p3 = Promise.resolve('ccc')
    let pms1 = Promise.all([p1,p2,p3])
    console.log(pms1)
</script>
7.2.2、结果

在这里插入图片描述

8、Promise.race

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

  1. promises:包含n个promise的数组

说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态

8.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        setTimeout(()=>{
            resolve('aaa')
        })
    })
    let p2 = new Promise((resolve,reject) => {
        resolve('bbb')
    })
    let pms1 = Promise.race([p1,p2]);
    console.log(pms1)
</script>

8.2、结果

在这里插入图片描述

Promise关键问题

1、如何改变promise的状态?

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

1.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        resolve('aaa')
    })

    let p2 = new Promise((resolve,reject) => {
        reject('bbb')
    })

    let p3 = new Promise((resolve,reject) => {
        throw 'ccc';
    })

    console.log("p1",p1) // 成功
    console.log("p2",p2) // 失败
    console.log("p3",p3) // 失败
</script>

1.2、结果

在这里插入图片描述

2、一个promise指定多个成功/失败的回调函数,都会调用吗?

当promise改变为对应状态时都会调用

2.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        resolve('aaa')
    })

    p1.then((resolve) => {
        console.log('aaa1:',resolve)
    })

    p1.then((resolve) => {
        console.log('aaa2:',resolve)
    })
</script>

2.2、结果

在这里插入图片描述

3、改变promise状态和指定回调函数谁先谁后?

  1. 都有可能,正常情况下实现指定回调再改变状态,但也可以先改变状态再指定回调
  2. 如何先改状态再指定回调?
    1. 再执行器中直接调用resolve()/reject()
    2. 延迟更长时间才调用then()
  3. 什么时候才能得到数据?
    1. 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
    2. 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据

3.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        // 1.先改变状态
        resolve('aaa')
    })

    p1.then(resolve => {
        // 2.调用回调函数
    })

// -----------------------------------------------------

    let p2 = new Promise((resolve,reject) => {
        // 2.然后改变状态
        setTimeout(() => {
            resolve('aaa')
        },1000)
    })

    // 1.先指定回调
    p2.then(resolve => {
        // 3.状态改变后回调函数调用。
    })

</script>

4、promise.then()返回的新的promise的结果状态由什么决定?

  1. 简单表达:由then()指定的回调函数执行的结果决定
  2. 详细表达:
    1. 如果抛出异常,新promise变为rejected,reason为抛出的异常
    2. 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
    3. 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果

4.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        // 1.先改变状态
        resolve('aaa')
    })

    // 非promise的任意值
    let pThen1 = p1.then(value => {
        return 'pThen1'
    })
    console.log("pThen1:",pThen1) // 成功

    // 抛出异常
    let pThen2 = p1.then(value => {
        throw 'pThen2'
    })
    console.log("pThen2:",pThen2) // 失败

    // 返回失败的promise
    let pThen3 = p1.then(value => {
        return new Promise((resolve,reject) => {
            reject('pThen3')
        })
    })
    console.log("pThen3:",pThen3) // 失败
</script>

4.2、结果

在这里插入图片描述

5、promise如何串联多个操作任务?

  1. promise的then()返回一个新的promise,可以看成then()的链式调用
  2. 通过then的链式调用串连多个同步/异步任务

5.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        // 1.等待1秒
        setTimeout(()=>{
            console.log('aaa')
            resolve(true)
        },1000)
    })
    p1.then(value => {
        // 2.执行回调
        return new Promise((resolve,reject) => {
            // 3.等待1秒
            setTimeout(()=>{
                console.log('bbb')
                resolve('ccc')
            },1000)
        })
    }).then(value => {
        // 4.成功的promise。执行回调
        console.log(value) // ccc
    })
</script>

5.2、结果

在这里插入图片描述

6、promise异常穿透?

  1. 当使用promise的then链式调用时,可以在最后指定失败的回调
  2. 前面任何操作出了异常,都会传到最后失败的回调中处理

6.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        setTimeout(()=>{
            console.log('aaa')
            // 链子地方任意一处失败,只需要在链子的最后面写一个catch即可获取到
            reject(false)
        },1000)
    })
    p1.then(value => {
        return new Promise((resolve,reject) => {
            console.log('bbb')
            resolve('ccc')
        })
    }).then(value => {
        console.log(value) // ccc
    }).catch(reason => {
        // 上面的链子中,不管哪个地方失败,都会走catch方法
        console.error(reason)
    })
</script>

6.2、结果

在这里插入图片描述

7、中断promise链?

  1. 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
  2. 办法:再回调函数中返回一个pendding状态的promise对象

7.1、代码

<script>
    let p1 = new Promise((resolve,reject) => {
        setTimeout(()=>{
            console.log('aaa')
            resolve(true)
        },1000)
    })
    p1.then(value => {
        // 想在这里执行完后,不走下面回调
        console.log('bbb')
        return new Promise((resolve,reject) => {
            // 这个promise为pending状态
        })
    }).then(value => {
        console.log('ccc')
    }).catch(reason => {
        console.error(reason)
    })
</script>

7.2、结果

在这里插入图片描述

手写Promise

1、ES5 Function写法

1.1、初始化

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入手写Promise -->
    <script src="./test1.js"></script>
</head>
<body>
<script>
    let p = new Promise((resolve,reject) => {
        resolve("OK")
    })
    p.then(value => {
        console.log(value)
    },reason => {
        console.log(reason)
    })
</script>
</body>
</html>
promise
function Promise(executor) {

    function resolve(data){

    }
    function reject(data){

    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onResolve,onReject){

}

2、封装resolve、reject

promise
function Promise(executor) {
    // 初始状态为 pendding
	this.PromiseState = 'pendding';
    this.PromiseResult = null;
    
    let that = this;
    function resolve(data){
        // 首先改变状态 PromiseState属性
        that.PromiseState = 'fulfilled'
        // 然后给结果赋值 PromiseResult属性
        that.PromiseResult = data;
    }
    function reject(data){
        // 首先改变状态 PromiseState属性
        that.PromiseState = 'rejected'
        // 然后给结果赋值 PromiseResult属性
        that.PromiseResult = data;
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onResolve,onReject){

}
结果

在这里插入图片描述

3、封装throw后状态结果

抛出异常后,Promise会变为失败状态,失败后的值,就是throw的内容。

只需要把 executor try catch住即可

html里js
<script>
    let p = new Promise((resolve,reject) => {
        // reject("OK")
        throw "error"
    })
    p.then(value => {
        console.log(value)
    },reason => {
        console.log(reason)
    })
    console.log(p)
</script>
promise
function Promise(executor) {
	this.PromiseState = 'pendding';
    this.PromiseResult = null;
    
    let that = this;
    function resolve(data){
        // 首先改变状态 PromiseState属性
        that.PromiseState = 'fulfilled';
        // 然后给结果赋值 PromiseResult属性
        that.PromiseResult = data;
    }
    function reject(data){
        // 首先改变状态 PromiseState属性
        that.PromiseState = 'rejected';
        // 然后给结果赋值 PromiseResult属性
        that.PromiseResult = data;
    }
    // 抛出异常
    try {
        executor(resolve,reject);
    }catch (e) {
        // that.PromiseState = 'rejected';
        // that.PromiseResult = e;
        reject(e)
    }
}

Promise.prototype.then = function(onResolve,onReject){

}
结果

在这里插入图片描述

4、promise状态只能修改一次

想要状态修改一次,我们只需要在修改状态前进行判断即可

html里js
<script>
    let p = new Promise((resolve,reject) => {
        resolve("ok") // 只走这一次
        reject("error")
    })
    p.then(value => {
        console.log(value)
    },reason => {
        console.log(reason)
    })
    console.log(p)
</script>
promise
function Promise(executor) {
    this.PromiseState = 'pendding';
    this.PromiseResult = null;
    let that = this;
    function resolve(data){
        if (that.PromiseState === 'pendding'){
            // 判断状态是否改变
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'fulfilled';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;
        }
        
    }
    function reject(data){
        if (that.PromiseState === 'pendding') {
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'rejected';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;
        }
    }
    // 抛出异常
    try {
        executor(resolve,reject);
    }catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function(onResolve,onReject){

}
结果

在这里插入图片描述

5、then方法执行回调

执行回调,判断promise状态,执行相应的回调函数

promise
function Promise(executor) {
    this.PromiseState = 'pendding';
    this.PromiseResult = null;
    let that = this;
    function resolve(data){
        if (that.PromiseState === 'pendding'){
            // 判断状态是否改变
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'fulfilled';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;
        }

    }
    function reject(data){
        if (that.PromiseState === 'pendding') {
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'rejected';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;
        }
    }
    // 抛出异常
    try {
        executor(resolve,reject);
    }catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function(onResolve,onReject){
    // 由于是p(promise)调用then方法,所以我们可以使用this
    if(this.PromiseState === 'fulfilled'){
        onResolve(this.PromiseResult)
    }else if(this.PromiseState === 'rejected'){
        onReject(this.PromiseResult)
    }
}
结果

在这里插入图片描述

6、异步任务回调执行

1.then回调函数异步

此时我们把引入的js文件注释掉,可以发现,then方法是异步任务,先打印的P,然后再执行then方法里的函数。我们这个是先执行then方法里的函数,然后才打印的p,在then方法里调用回调函数外面包一层setTimeout即可

2.executor函数异步

当executor函数为异步函数时,then回调函数要等executor执行完毕后,再执行。所以我们要在executor执行完毕后再调用then方法

html里js
<script>
    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("ok")
        },1000)
    })
    p.then(value => {
        console.log(value)
    },reason => {
        console.log(reason)
    })
    console.log("p",p)
</script>
promise
function Promise(executor) {
    this.PromiseState = 'pendding';
    this.PromiseResult = null;
    this.callBack = {};

    let that = this;
    function resolve(data){
        if (that.PromiseState === 'pendding'){
            // 判断状态是否改变
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'fulfilled';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;

            // 执行完毕后,调用then方法
            if(that.callBack.res){
                that.callBack.res(data)
            }
        }

    }
    function reject(data){
        if (that.PromiseState === 'pendding') {
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'rejected';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;

            // 执行完毕后,调用then方法
            if(that.callBack.rej){
                that.callBack.rej(data)
            }
        }
    }
    // 抛出异常
    try {
        executor(resolve,reject);
    }catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function(onResolve,onReject){
    setTimeout(() => {
        // 由于是p(promise)调用then方法,所以我们可以使用this
        if(this.PromiseState === 'fulfilled'){
            onResolve(this.PromiseResult);
        }else if(this.PromiseState === 'rejected'){
            onReject(this.PromiseResult);
        }else if(this.PromiseState === 'pendding'){
            // 需要先把方法保存起来,才能在上面调用
            this.callBack.res = onResolve;
            this.callBack.rej = onReject;
        }
    })
}
结果

在这里插入图片描述

7、指定多个回调函数

当我们按照上面的代码写的时候,这时候当我们执行两个then方法,这时候只会走最后一个方法,因为最后一个方法在then方法里,把上面的方法替换掉了,所以只会走最后一个,这时候我们要把callBack变为数组,遍历以此执行

html里js
<script>
    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("ok")
        },1000)
    })
    p.then(value => {
        console.log('111')
    },reason => {
        console.log(reason)
    })

    p.then(value => {
        console.log('222')
    },reason => {
        console.log(reason)
    })
    console.log("p",p)
</script>
promise
function Promise(executor) {
    this.PromiseState = 'pendding';
    this.PromiseResult = null;
    this.callBack = [];

    let that = this;
    function resolve(data){
        if (that.PromiseState === 'pendding'){
            // 判断状态是否改变
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'fulfilled';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;

            // 执行完毕后,调用then方法
            that.callBack.forEach(item => {
                item.res(data);
            })
        }

    }
    function reject(data){
        if (that.PromiseState === 'pendding') {
            // 首先改变状态 PromiseState属性
            that.PromiseState = 'rejected';
            // 然后给结果赋值 PromiseResult属性
            that.PromiseResult = data;

            // 执行完毕后,调用then方法
            that.callBack.forEach(item => {
                item.rej(data);
            })
        }
    }
    // 抛出异常
    try {
        executor(resolve,reject);
    }catch (e) {
        reject(e)
    }
}

Promise.prototype.then = function(onResolve,onReject){
    setTimeout(() => {
        // 由于是p(promise)调用then方法,所以我们可以使用this
        if(this.PromiseState === 'fulfilled'){
            onResolve(this.PromiseResult);
        }else if(this.PromiseState === 'rejected'){
            onReject(this.PromiseResult);
        }else if(this.PromiseState === 'pendding'){
            // 需要先把方法保存起来,才能在上面调用
            this.callBack.push({
                res:onResolve,
                rej:onReject
            })
        }
    })
}
结果

在这里插入图片描述

8、同步修改状态then方法的返回结果

then方法要返回一个promise对象,

  • 如果返回值为promise外其他类型,则为成功的promise,值为返回的值

  • 如果返回值为promise类型,则根据这个promise的返回结果来改变返回值的返回结果

html里js
<script>
    let p = new Promise((resolve,reject) => {
        // setTimeout(() => {
            resolve("ok")
        // },1000)
    })
    let then1 = p.then(value => {
        console.log('111')
        // 返回的是undefined
    },reason => {
        console.log(reason)
    })

    let then2 = p.then(value => {
        return new Promise((resolve,reject) => {
            resolve('OOKK')
        })
    },reason => {
        console.log(reason)
    })
    console.log("then1",then1)
    console.log("then2",then2)
</script>
promise then方法
Promise.prototype.then = function(onResolve,onReject){
	return new Promise((resolve,reject) => {
        setTimeout(() => {
            // 由于是p(promise)调用then方法,所以我们可以使用this
            if(this.PromiseState === 'fulfilled'){
                const resout = onResolve(this.PromiseResult);
                if (resout instanceof Promise){
                    resout.then(value => {
                        resolve(value);
                    },reason => {
                        reject(reason);
                    })
                }else {
                    resolve(resout);
                }
            }else if(this.PromiseState === 'rejected'){
                const resout = onReject(this.PromiseResult);
                if (resout instanceof Promise){
                    resout.then(value => {
                        resolve(value);
                    },reason => {
                        reject(reason);
                    })
                }else {
                    resolve(resout);
                }
            }else if(this.PromiseState === 'pendding'){
                // 需要先把方法保存起来,才能在上面调用
                this.callBack.push({
                    res:onResolve,
                    rej:onReject
                })
            }
        })
    })
}
结果

在这里插入图片描述

9、异步修改状态then方法的返回结果

由于executor执行完毕后只会执行回调,并不会执行回调中promise中的resolve和reject方法,导致then方法返回的promise始终为pendding状态

并且我们要判断then里面throw抛出异常后promise的状态

html里js
<script>
    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("ok")
        },1000)
    })
    let then1 = p.then(value => {
        console.log(value)
        // 返回的是undefined
    },reason => {
        console.log(reason)
    })

    let then2 = p.then(value => {
        return 'OOKK'
    },reason => {
        console.log(reason)
    })

    let then3 = p.then(value => {
        throw 'error'
    },reason => {
        console.log(reason)
    })

    console.log(then1)
    console.log(then2)
    console.log(then3)
</script>
promise then方法
Promise.prototype.then = function(onResolve,onReject){
	return new Promise((resolve,reject) => {
        setTimeout(() => {
            // 由于是p(promise)调用then方法,所以我们可以使用this
            if(this.PromiseState === 'fulfilled'){
                try {
                    const result = onResolve(this.PromiseResult);
                    if (result instanceof Promise){
                        result.then(value => {
                            resolve(value);
                        },reason => {
                            reject(reason);
                        })
                    }else {
                        resolve(result);
                    }
                }catch (e) {
                    reject(e);
                }

            }else if(this.PromiseState === 'rejected'){
                try {
                    const result = onReject(this.PromiseResult);
                    if (result instanceof Promise){
                        result.then(value => {
                            resolve(value);
                        },reason => {
                            reject(reason);
                        })
                    }else {
                        resolve(result);
                    }
                }catch (e) {
                    reject(e)
                }

            }else if(this.PromiseState === 'pendding'){
                // 需要先把方法保存起来,才能在上面调用
                this.callBack.push({
                    res: () => {
                        try {
                            // 获取then回调的返回值
                            let result = onResolve(this.PromiseResult)
                            if (result instanceof Promise){
                                result.then(value => {
                                    resolve(value);
                                },reason => {
                                    reject(reason);
                                })
                            }else {
                                resolve(result);
                            }
                        }catch (e) {
                            reject(e)
                        }

                    },
                    rej: () => {
                        try {
                            let result = onReject(this.PromiseResult)
                            if (result instanceof Promise){
                                result.then(value => {
                                    resolve(value);
                                },reason => {
                                    reject(reason);
                                })
                            }else {
                                resolve(result);
                            }
                        }catch (e) {
                            reject(e);
                        }

                    },
                })
            }
        })
    })
}
结果

在这里插入图片描述

10、then方法优化和完善

then方法里很多代码是重复代码,我们需要单独提取出来

promise
Promise.prototype.then = function(onResolve,onReject){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            // 封装函数
            const handleThen = (type) => {
                try {
                    const result = type(this.PromiseResult);
                    if (result instanceof Promise){
                        result.then(value => {
                            resolve(value);
                        },reason => {
                            reject(reason);
                        })
                    }else {
                        resolve(result);
                    }
                }catch (e) {
                    reject(e);
                }
            }
            // 由于是p(promise)调用then方法,所以我们可以使用this
            if(this.PromiseState === 'fulfilled'){
                handleThen(onResolve);
            }else if(this.PromiseState === 'rejected'){
                handleThen(onReject);
            }else if(this.PromiseState === 'pendding'){
                // 需要先把方法保存起来,才能在上面调用
                this.callBack.push({
                    res: () => {
                        handleThen(onResolve);
                    },
                    rej: () => {
                        handleThen(onReject);
                    },
                })
            }
        })
    })
}
结果

在这里插入图片描述

11、封装catch方法

html里js

<script>
    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            reject("error")
        },1000)
    })
    p.catch(e => {
        console.log(e)
    })

    console.log(p)
</script>

promise catch方法

Promise.prototype.catch = function (onReject){
    return this.then(undefined,onReject);
}

11、异常穿透与值传递

  1. 如果promise途中失败了,在then里面只写成功的回调方法,不写失败的,那么控制台就会报错,找不到onReject方法,我们要判断如果没有方法,就默认加一个
  2. 当我第一个then什么回调都没有写的时候,值会传递到第二个then中,并且顺利执行
html里js
<script>
    let p = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("error")
        },1000)
    })
    p.then().then(value => {
        console.log(value + '1')
    }).then(value => {
        console.log(value + '2')
    }).catch(reason => {
        console.log(reason + '3')
    })

</script>
promise then方法
Promise.prototype.then = function(onResolve,onReject){
    return new Promise((resolve,reject) => {
        // 处理失败回调没有的情况
        if (typeof onReject !== "function"){
            // 往上抛,直到抛到catch
            onReject = reason => {
                throw reason
            };
        }
        // 处理成功回调没有的情况
        if(typeof onResolve !== "function"){
            onResolve = value => {
                return value
            }
        }
        setTimeout(() => {
            // 封装函数
            const handleThen = (type) => {
                try {
                    const result = type(this.PromiseResult);
                    if (result instanceof Promise){
                        result.then(value => {
                            resolve(value);
                        },reason => {
                            reject(reason);
                        })
                    }else {
                        resolve(result);
                    }
                }catch (e) {
                    reject(e);
                }
            }
            // 由于是p(promise)调用then方法,所以我们可以使用this
            if(this.PromiseState === 'fulfilled'){
                handleThen(onResolve);
            }else if(this.PromiseState === 'rejected'){
                handleThen(onReject);
            }else if(this.PromiseState === 'pendding'){
                // 需要先把方法保存起来,才能在上面调用
                this.callBack.push({
                    res: () => {
                        handleThen(onResolve);
                    },
                    rej: () => {
                        handleThen(onReject);
                    },
                })
            }
        })
    })
}
结果

在这里插入图片描述

12、resolve静态方法封装

html里js
<script>
    let p1 = Promise.resolve('111')
    let p2 = Promise.resolve(new Promise((resolve,reject) => {resolve('OK')}))
    let p3 = Promise.resolve(new Promise((resolve,reject) => {reject('ERROR')}))
    let p4 = Promise.resolve(new Promise((resolve,reject) => {throw 'error'}))

    console.log("p1",p1)
    console.log("p2",p2)
    console.log("p3",p3)
    console.log("p4",p4)
</script>
promise resolve静态方法
Promise.resolve = function (data){
    return new Promise((onResolve,onReject) => {
        if (data instanceof Promise){
            data.then(resolve => {
                onResolve(resolve)
            },reject => {
                onReject(reject)
            })
        }else {
            onResolve(data)
        }
    })
}
结果

在这里插入图片描述

13、reject静态方法封装

html里js
<script>
    let p1 = Promise.reject('111')
    let p2 = Promise.reject(new Promise((resolve,reject) => {resolve('OK')}))
    let p3 = Promise.reject(new Promise((resolve,reject) => {reject('ERROR')}))
    let p4 = Promise.reject(new Promise((resolve,reject) => {throw 'error'}))

    console.log("p1",p1)
    console.log("p2",p2)
    console.log("p3",p3)
    console.log("p4",p4)
</script>
promise reject静态方法
Promise.reject = function (data){
    return new Promise((resolve,reject) => {
        reject(data)
    })
}
结果

在这里插入图片描述

14、all静态方法封装

html里js
<script>
    let p1 = Promise.resolve('111')
    let p2 = new Promise((resolve,reject) => {
        resolve('OK2')
    })
    let p3 = new Promise((resolve,reject) => {
        // reject('Error3')
        resolve('OK3')
    })
    let all = Promise.all([p1,p2,p3,'aaa']);
    console.log(all)

</script>
promise all静态方法
Promise.all = function (datas){
    return new Promise((onResolve,onReject) => {
        let resouts = []
        let count = 0;
        for (let i = 0; i < datas.length; i++) {
            const data = datas[i];
            debugger
            if(data instanceof Promise){
                data.then(resolve => {
                    resouts[i] = resolve;
                    count++;
                    if(count === datas.length){
                        onResolve(resouts)
                    }
                },reject => {
                    onReject(reject)
                })
            }else {
                resouts[i] = data
                count++;
                if(count === datas.length){
                    onResolve(resouts)
                }
            }

        }
    })
}
结果
全部成功

在这里插入图片描述

一个失败

在这里插入图片描述

15、race静态方法封装

html里js
<script>
    let p1 = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('OK1')
        })
    })
    let p2 = new Promise((resolve,reject) => {
        resolve('OK2')
    })
    let all = Promise.race([p1,p2,'aaa']);
    console.log(all)

</script>
promise race静态方法
Promise.race = function (datas){
    return new Promise((onResolve,onReject) => {
        for (let i = 0; i < datas.length; i++) {
            let data = datas[i];
            if(data instanceof Promise){
                data.then(value => {
                    onResolve(value)
                },reason => {
                    onReject(reason)
                })
            }else {
                // 弥补then方法的异步时间
                setTimeout(() => {
                    onResolve(data);
                })
            }
        }
    })
}
结果

在这里插入图片描述

2、ES6 Class写法

注意:静态方法前面要添加static关键字!!!

class Promise {
    constructor(executor) {
        this.PromiseState = 'pendding';
        this.PromiseResult = null;
        this.callBack = [];
        let that = this;
        function resolve(data){
            if (that.PromiseState === 'pendding'){
                // 判断状态是否改变
                // 首先改变状态 PromiseState属性
                that.PromiseState = 'fulfilled';
                // 然后给结果赋值 PromiseResult属性
                that.PromiseResult = data;

                // 执行完毕后,调用then方法
                that.callBack.forEach(item => {
                    item.res(data);
                })
            }

        }
        function reject(data){
            if (that.PromiseState === 'pendding') {
                // 首先改变状态 PromiseState属性
                that.PromiseState = 'rejected';
                // 然后给结果赋值 PromiseResult属性
                that.PromiseResult = data;

                // 执行完毕后,调用then方法
                that.callBack.forEach(item => {
                    item.rej(data);
                })
            }
        }
        // 抛出异常
        try {
            executor(resolve,reject);
        }catch (e) {
            reject(e)
        }
    }

    then(onResolve,onReject) {
        return new Promise((resolve, reject) => {
            // 处理失败回调没有的情况
            if (typeof onReject !== "function") {
                // 往上抛,直到抛到catch
                onReject = reason => {
                    throw reason
                };
            }
            // 处理成功回调没有的情况
            if (typeof onResolve !== "function") {
                onResolve = value => {
                    return value
                }
            }
            setTimeout(() => {
                // 封装函数
                const handleThen = (type) => {
                    try {
                        const result = type(this.PromiseResult);
                        if (result instanceof Promise) {
                            result.then(value => {
                                resolve(value);
                            }, reason => {
                                reject(reason);
                            })
                        } else {
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                // 由于是p(promise)调用then方法,所以我们可以使用this
                if (this.PromiseState === 'fulfilled') {
                    handleThen(onResolve);
                } else if (this.PromiseState === 'rejected') {
                    handleThen(onReject);
                } else if (this.PromiseState === 'pendding') {
                    // 需要先把方法保存起来,才能在上面调用
                    this.callBack.push({
                        res: () => {
                            handleThen(onResolve);
                        },
                        rej: () => {
                            handleThen(onReject);
                        },
                    })
                }
            })
        })
    }

    catch(onReject){
        return this.then(undefined,onReject);
    }

    static resolve(data){
        return new Promise((onResolve,onReject) => {
            if (data instanceof Promise){
                data.then(resolve => {
                    onResolve(resolve)
                },reject => {
                    onReject(reject)
                })
            }else {
                onResolve(data)
            }
        })
    }

    static reject(data){
        return new Promise((resolve,reject) => {
            reject(data)
        })
    }

    static all(datas){
        return new Promise((onResolve,onReject) => {
            let resouts = []
            let count = 0;
            for (let i = 0; i < datas.length; i++) {
                const data = datas[i];
                debugger
                if(data instanceof Promise){
                    data.then(resolve => {
                        resouts[i] = resolve;
                        count++;
                        if(count === datas.length){
                            onResolve(resouts)
                        }
                    },reject => {
                        onReject(reject)
                    })
                }else {
                    resouts[i] = data
                    count++;
                    if(count === datas.length){
                        onResolve(resouts)
                    }
                }

            }
        })
    }

    static race(datas){
        return new Promise((onResolve,onReject) => {
            for (let i = 0; i < datas.length; i++) {
                let data = datas[i];
                if(data instanceof Promise){
                    data.then(value => {
                        onResolve(value)
                    },reason => {
                        onReject(reason)
                    })
                }else {
                    // 弥补then方法的异步时间
                    setTimeout(() => {
                        onResolve(data);
                    })
                }
            }
        })
    }
}

async与await

async

  1. 函数的返回值为promise对象

  2. promise对象的结果由async函数执行的返回值决定

    <script>
        async function test1(){
            return 'aaa'
        }
    
        async function test2(){
            return new Promise((resolve,reject) => {
                resolve("我成功啦")
            })
        }
    
        console.log("test1",test1())
        console.log("test2",test2())
    </script>
    

    在这里插入图片描述

await

  1. await右侧的表达式一般为promise对象,但也可以是其它的值

  2. 如果表达式是promise对象,await返回的结果时promise成功的值

  3. 如果表达式是其它值,直接将此值作为await的返回值

    <script>
        async function test1(){
            let a = await 'aaa';
            console.log("a",a);
            let b = await Promise.resolve('bbb')
            console.log("b",b)
        }
    
        test1()
    </script>
    

    在这里插入图片描述

注意

  1. await必须卸载async函数中,但async函数中可以没有await

  2. 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理

    <script>
        /*function test1(){ 报错
            await 'aaa';
        }*/
    
        async function test1(){
            let a = '';
            try {
                // 失败
                p = new Promise((resolve,reject) => {
                    reject('我失败了')
                })
                // 抛出异常
                a = await p;
            }catch (e){
                a = '我真的失败了'
            }
            console.log(a)
        }
    
        test1()
    </script>
    

    在这里插入图片描述

OK,Promise课程到此结束,欢迎下期再见~Bye

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值