Promise的前提概念

Promise是一个构造函数,用来生成Promise实例
Promise构造函数承受一个函数作为参数,该函数有两个参数,别离是resolvereject
resolve:胜利时的回调
reject:失败时的回调

Promise别离有三个状态
1、pending :进行中
2、fulfilled:已胜利
3、rejected:已失败

Promise的执行
Promise一旦新建后就会立马执行,无奈中途勾销,Promise返回的只有两种状态,并且该状态产生就无奈更改。也就是说Promise的状态只有以下两种状况:
1、从pendingfulfilled
2、从pendingrejected
pending的状态一旦扭转,就不会再发生变化。

Promise的后果返回
Promise外部后果一旦返回,resolvereject其中的任何一种,即可产生回调。
1、resolve的回调在then()中获取(胜利的回调)
2、reject的回调在cathc()中获取(失败,捕捉谬误)

let promise = new Promise(function(resolve,reject){     // sth...     let i = 5;     if( i > 1){         resolve(i) // 胜利     } else {          reject(error) // 失败     }})    promise.then(el=>{     // el即为resolve的参数     console.log(el);  // 5    })    .catch(err=>{        console.log(err);    })


Promise的执行程序
Promise创立后会立马执行,then()是一个异步回调,将在所有的同步工作执行完后执行then(),也就是说:Promise在新建的时候会立刻执行,then()catch()为异步工作,当所有同步工作执行完后才会执行then()

let pro = new Promise(function(resolve,reject){    console.log('Promise新建');    resolve()})pro.then(el=>{   console.log('.then回调');})console.log('同步工作');


上述代码的执行后果:
1、Promise新建
2、同步工作
3、then()回调


Promise参数和执行程序

resolve函数的参数出了能够携带正常值以外,还能够携带Promise实例

let pro = new Promise(function(resolve,reject){let i = 10    if(i < 50){        resolve(i)    } else {        reject(error)   }})let pro2 = new Promise(function(resolve,reject){    resolve(pro)  // 参数为上一个Promise实例})      pro2.then(el=>{     console.log(el);  // 10    })    .catch(err=>{     console.log(err);    })

执行程序:
先执行pro,如果pro的状态是pending时,pro2则会期待执行,当pro的状态变成resolverejected时,pro2则会立马执行,因为pro决定pro2的状态,所以前面的then变成了针对pro


Promise的嵌套执行

let p = new Promise((resolve,reject)=>{     let i = 10     if(i > 5){         resolve(i)     } else {         reject('pro谬误')     }})let p2 = new Promise((resolve,reject)=>{    p.then(el=>{        console.log(el * 2);  // 20        if(el > 6){        // 此处须要写成return resolve(el)看起来会更失常           resolve(el)           console.log('我是p1的.then回调');  // 我是p1的.then回调        } else {            reject('pro2谬误')        }    })   })   let p3 = new Promise((resolve,reject)=>{    p2.then(el=>{        if(el > 50){            resolve(el)        } else {            reject('pro3谬误')        }    })})

多个Promise的执行程序:
新建Promise后会立马执行,先执行Promise内的工作,执行实现后再执行then()
如果Promise内有其它Promisethen()工作执行(这里简称p2),会先将p2then()工作执行结束,再执行本身的then()工作
多个Promise并行,会先按程序执行Promise的工作,再别离依照程序别离执行他们的then()工作

须要留神的是:下面p2Promse中,失常来说,resolvereject执行完后,Promise的使命应该实现,但此处因为执行程序的问题,并没有先执行resolve,而是执行了console的工作,因该写成return resolve(value)的模式,让Promise更失常一些,否则会呈现不必要的意外。


Promise.prototype.then()

then办法是定义在原型对象Promise.prototype上的,它能够为Promise实例增加状态扭转时的回调函数。
then有两个参数(可选):
resolved:胜利状态的回调函数
rejected:失败状态的回调函数
then返回的是一个新的Promise实例,因而能够采纳链式写法,then()前面还能够接then()

let p = new Promise((resolve,reject)=>{    let i = 5;    if(i > 4){        resolve(i)    } })p.then(el=>{    console.log('then1:'+ el);    if(el > 3){       return el    }}).then(el=>{    console.log('then2:'+ el * 2);}).catch(err=>{    console.log(err);} /*   输入后果:   then1:5   then2:10*/

下面代码应用then办法,第一个then()回调函数执行完后,会将返回后果传入第二个回调函数,也就是说,第二个then()的参数是第一个then()返回的后果。
catch的捕捉具备冒泡性质,也就是说,后面不管.then了多少次,外面产生的谬误,都会被最初一个catch捕捉到。


Promise.prototype.catch()

Promise.prototype.catch()办法是.then(null,rejection)的别名,也就是说,catch其实是用来指定产生谬误时的回调函数。

let p = new Promise((resolve,reject)=>{        reject('错误信息')   })   p.then(el=>{    // sth...  }).catch(err=>{    console.log(err);  // 错误信息  })

上述代码中,p办法返回Promise对象,该对象返回的是rejectthen()办法调用回调函数,then()有两个参数,一个resolvedrejected,如果Promise返回的是reject,那么.then的状态就会变成rejectedrejected会调用catch()办法指定的回调函数,解决该谬误,catch的参数就是reject抛出的错误信息。

如果then运行中抛出谬误,也会被catch()捕捉

let p2 = new Promise((resolve,reject)=>{    resolve(100)   })p2.then(el=>{    throw new Error('then抛错')}).catch(err=>{    console.log(err);  // Error: then抛错})

catch捕获谬误的形式

   // 形式一let promise = new Promise(function(resolve,reject){    try {       throw new Error('形式一谬误')    } catch(e){         reject(e)    }})promise.catch(err=>{   console.log(err);  //  形式一谬误   })
// 形式二let promise2 = new Promise(function(resolve,reject){    reject(new Error('形式二谬误'))})promise2.catch(err=>{      console.log(err);  //  形式二谬误   })
// 形式三let promise3 = new Promise((resolve,reject)=>{      reject('形式三谬误')   })   promise3.catch(err=>{      console.log(err);  // 形式三谬误   })

以上三种成果是一样的,前两种通过Error抛出异样,后一种间接抛出异样
catch返回的也是一个Promise对象,前面还能够接着调用then()办法
如果Promise的状态变成resolved,那么再抛出谬误是有效的,因为Promise的状态一旦产生扭转,就会永恒放弃该状态。

执行阻塞问题
Promise外部谬误不会影响到到异步队列中的Promise内部代码,同步代码还是会造成阻塞

let p3 = new Promise((resolve,reject)=>{      resolve(str)  // ReferenceError: str is not defined})p3.then(el=>{console.log(el)})setTimeout(()=>{console.log('Promise内部代码')},1000)  // Promise内部代码console.log('同步代码');  // 未打印


Promise在建设时会立刻执行,此处报错了,所以前面的同步代码都无奈执行,然而异步的setTimeout还是会执行,并不受影响。


finally()

finally有最初、终于的意思,也就是说finally()办法不论Promise最初的状态如何,都会执行

let p = new Promise((resolve,reject)=>{            resolve('东方不败')})p.then(el=>{    console.log(el);  // 东方不败}).catch(err=>{    console.log(err);}).finally(()=>    console.log('finally执行')  // finally执行)


上述代码中,不论Promise最初的状态怎么样,finally都会执行,即便没有then()catch()finally也会执行

须要留神的是,finally不承受任何参数,然而finally的执行程序跟外部是否是一个函数无关,如果finally外部是一个函数,那么finally会在Promise最初执行,如果finally外部没有任何函数,间接输入,那么finally会在Promise最后面执行。

finally的执行跟Promise的状态无关。


Promise.all()

Promise.all()办法用于将多个Promise实例包装成一个新的Promise实例
语法:let p = Promise.all([p1,p2,p3])

let p = new Promise((resolve,reject)=>{    resolve(10)})p.then(el=>{    console.log(el);})        let p2 = new Promise((resolve,reject)=>{    // resolve(20)    reject(20)})p2.then(el=>{    console.log(el);}).catch(err=>{console.log('p2:',err);})// p、p2都返回resolve则触发该函数Promise.all([p,p2])       .then(el=>{           console.log(el);        })        .catch(err=>{console.log('all:',err);})  // all:20

Promise.all的两个promise参数状态都变成fulfilled时,才会触发Promise.all()的办法,如果其中以一个参数被rejected,那么Promise.all()也会变成rejected的状态,会被catch捕获。
下面代码中,如果p2没有chach办法,则会调用Promise.all()catch


race()

Promise.race()办法能够将多个Promise实例包装成一个新的Promise实例。
语法: let p = Promise.race([p1,p2,p3])

let p = new Promise((resolve,reject)=>{      setTimeout(()=>{            resolve('p1状态')      },2000)    })    let p2 = new Promise((resolve,reject)=>{      setTimeout(()=>{            resolve('p2状态')       },1000)     })     let p3 = new Promise((resolve,reject)=>{       setTimeout(()=>{            resolve('p3状态')       },3000)     })     let p4 = new Promise((resolve,reject)=>{       setTimeout(()=>{            reject('reject:p4状态')        },4000)      })let promise = Promise.race([p,p2,p3,p4])promise.then(el=>{    console.log(el);  // p2状态}).catch(err=>{    console.log(err);})

race有竞争,角逐的意思,该办法其实就是参数中,哪一个Promise的状态先产生扭转,就调用先产生扭转的promise,这个el就是最先产生扭转的promise的返回值。


Promise.allSettled()

Promise.allSettled()办法能够在所有异步操作都完结的状况下,调用该办法。它与Promise.all()办法不同的是,all()办法须要所有异步都胜利才会进入then(),而allSettled()不须要。

let p = new Promise((resolve,reject)=>{      resolve('p1状态')})        let p2 = new Promise((resolve,reject)=>{       setTimeout(()=>{         reject('p2状态')       },3000)})Promise.allSettled([p,p2]).then(el=> console.log(el) )


Promise.allSettled()的参数不论是reject还是resolve都会触发,只有参数的状态全都产生扭转即可,下面代码中,p2提早了3s状态才产生扭转,那么Promise.allSettled()则会期待参数的状态全都产生扭转时触发。


Promise.any()

Promise.any()办法承受一组Promise实例作为参数,包装成一个新的Promise实例返回。

let p = new Promise((resolve,reject)=>{      resolve('p1状态')})        let p2 = new Promise((resolve,reject)=>{      reject('p2状态')})Promise.any([p,p2])       .then(el=>{          console.log('then:',el);  // then: p1状态       })       .catch(err=>{          console.log('catch:',err);       })

只有有一个参数的状态变成fulfilledPromise.any就会变成fulfilled状态
如果所有的参数实例都变成rejected状态,包装实例才会变成rejected状态
也就是说,any是只有有一个参数胜利,any就能够then,所有参数都rejectany才会catch


Promise.resolve()

Promise.resolve()能够将现有对象转为Promise对象,Promise.resolve()办法就起到这个作用。
语法:let p = Promise.resolve(obj)

let p = Promise.resolve('obj')p.then(el=> console.log(el))  // obj// 其实相当于let p2 = new Promise(resolve=>resolve('obj'))

如果Promise.resolve()没有参数,那么将间接返回resolved状态的Promise对象,并且是一个没有参数的then()办法。

let p3 = Promise.resolve()p3.then(el=>{     console.log(el);  // undefined})setTimeout(()=>{     console.log('定时器');},0)Promise.resolve()       .then(()=>{         setTimeout(()=>{console.log('resolve内定时器')},0)         console.log('resolve外部');        })console.log('内部');


Promise的执行程序,Promise是一个异步的微工作,同步工作执行完后才会执行异步工作,异步的微工作会先执行,微工作执行完后才会执行异步的宏工作,此处的setTimeout是异步的宏工作,所以会最初执行,内部的定时器是异步的宏工作,Promise外部的定时器是异步微工作内的宏工作,所以微工作内的宏工作会更慢执行,此处的执行程序为:内部、resolve外部、定时器、resolve内定时器。


Promise.reject()

Promise.reject()返回一个新的Promise实例,该实例的状态为rejected

let p = Promise.reject('错误信息')p.catch(err=>console.log(err))// 等同于let p2 = new Promise((resolve,reject)=>{    reject('错误信息2')})p2.catch(err=>console.log(err))


Promise.try()

理论开发中,会遇到这么一种状况,不论函数是同步还是异步的,都想用Promise来解决它,因为这样就能够用then()指定下一步流程,catch解决抛出的谬误,更便于管理流程。
基于Promise咱们能够用async做到同步的代码格调执行异步操作,当初有一个最新的提案,应用Promise.try()来捕捉所有的同步和异步谬误。
为什么这么做?
Promise抛出的谬误,catch能够捕捉到,但此处仅限于以后Promise的异样谬误,也就是异步的。如果同步谬误抛出,那么catch()是捕获不到的,须要在外层再嵌套一层try...catch,这样写起来十分麻烦,代码如下:

try {   let p = new Promise((resolve,reject)=>{           reject('异步谬误')       })   p.catch(err=> void console.log(err) )  // 异步谬误   throw Error('同步谬误')      } catch (e) {    console.log(e);  // 同步谬误}// 这样catch两次,能够解决同步和异步的抛错问题

如果应用Promise.try()就能够捕捉所有的同步和异步谬误

Promise.try(()=>{    let p2 = new Promise((resolve,reject)=>{        reject('异步谬误2')    })             throw Error('同步谬误2')    })    .then(el=>{        console.log('then:',el);     })    .catch(err=>{        console.log('catch:',err);    })

此处的Promise.try就相当于try代码块,Promise.catch就相当于catch代码块。


案例源码:https://gitee.com/wang_fan_w/es6-science-institute

如果感觉这篇文章对你有帮忙,欢送点亮一下star哟