Promise的实例方法
Promise的实例方法是连接外部同步代码和内部异步代码之间的桥梁,这些方法可以根据异步操作返回的数据在处理成功或失败的结果。
Promise.prototype.then()
then()是Promise处理程序的主要方法,它最多接受两个参数,第一个参数是对应上一个Promise为兑现(fulfilled)的处理方法,第二个参数是对rejected的处理方法
then方法会将上一个Promise的结果作为自己的参数使用,若上一个Promise的状态为resolve,那么then的第一个回调函数就拥有一个参数,即上一个Promise的结果,第二个回调函数也相同,它接受上一个被拒绝的Promise的结果当做参数
let p1=new Promise((resolve,reject)=>resolve('resolved promise'))
let p2=new Promise((resolve,reject)=>reject('rejected promise'))
let p11=p1.then((data)=>console.log(data))
let p21=p2.then(null,(res)=>console.log(res))
setTimeout(console.log,0,p11) //resolved promise
setTimeout(console.log,0,p21) //rejected promise
当上一个Promise结果为兑现(fulfilled)时就会调用then的第一个参数的回调函数,上一个Promise结果为拒绝时,就会调用then的第二个参数作为回调函数。
let p1=new Promise((resolve,reject)=>resolve())
let p2=new Promise((resolve,reject)=>reject())
let p3=p1.then(()=>{console.log('p1兑现了')},()=>{console.log('p1失败了')})
let p4=p2.then(()=>{console.log('p2兑现了')},()=>{console.log('p2失败了')})
//p1兑现了
//p2失败了
then()也会返回一个新的Promise,这个Promise的状态是根据处理函数的返回值来构建的,如果返回值是Promise,那么会根据这个返回的Promise状态来确定返回值的状态,如果不是Promise,就会默认以Promise.resolve()来包装这个值。
//返回值为Promise
let p1=new Promise((resolve,reject)=>resolve())
let p2=new Promise((resolve,reject)=>reject())
let p3=p1.then(()=>Promise.reject(),()=>Promise.resolve())
let p4=p2.then(()=>Promise.reject(),()=>Promise.resolve())
setTimeout(console.log,0,p3) //Promise {<rejected>: undefined}
setTimeout(console.log,0,p4) //Promise {<fulfilled>: undefined}
//返回值不为Promise
let p1=new Promise((resolve,reject)=>resolve())
let p2=new Promise((resolve,reject)=>reject())
let p11=p1.then(()=>'bar')
let p12=p1.then(()=> 1 )
let p13=p1.then(()=>{})
let p21=p2.then(null,()=>'bar')
let p22=p2.then(null,()=> 1 )
let p23=p2.then(null,()=>{})
setTimeout(console.log,0,p11) //Promise {<fulfilled>: 'bar'}
setTimeout(console.log,0,p12) //Promise {<fulfilled>: 1}
setTimeout(console.log,0,p13) //Promise {<fulfilled>: undefined}
setTimeout(console.log,0,p21) //Promise {<fulfilled>: 'bar'}
setTimeout(console.log,0,p22) //Promise {<fulfilled>: 1}
setTimeout(console.log,0,p23) //Promise {<fulfilled>: undefined}
并且,如果Promise的resolve或reject状态没有被then捕获到,那么它会以原先的状态,继续朝着Promise处理函数的方向前进,直到被正确捕获。
let p1=new Promise((resolve,reject)=>resolve(1))
let p2=new Promise((resolve,reject)=>reject(2))
let p11=p1.then(null,()=>{console.log('p1拒绝了')})
let p21=p2.then(()=>{console.log('p2兑现了'),null})
let p12=p11.then((data)=>{console.log(data)}) // 1
let p22=p21.catch((res)=>{console.log(res)}) // 2
值得注意的是,当返回值为throw与new Error这些错误值时,会有些许不同。
throw会把Promise的状态变为rejected,而Error却不会,仍然保持resolve。
let p1=new Promise((resolve,reject)=>resolve())
let p11=p1.then(()=>{throw 'throw error'})
let p12=p1.then(()=> Error('new Error') )
setTimeout(console.log,0,p11) //Promise {<rejected>: 'throw error'}
setTimeout(console.log,0,p12) //Promise {<fulfilled>: Error: new Error}
Promise.prototype.catch()
catch方法用于给Promise添加拒绝处理程序,只接受一个参数,就是如何处理错误,这个方法是一个语法糖,调用它等价于调用then的第二个参数的回调函数。
catch也会返回一个新的Promise,返回的Promise的状态与then方法返回的状态是一致的。
//catch返回新的Promise
let p1=new Promise(()=>{})
let p2=p1.catch()
setTimeout(console.log,0,p1) //Promise {<pending>}
setTimeout(console.log,0,p2) //Promise {<pending>}
setTimeout(console.log,0,p1===p2) //false
Promise.prototype.finally()
finally方法用于给Promise添加最终的处理程序,不论之前的Promise是成功或是失败都会执行
let p1=Promise.resolve()
let p2=Promise.reject()
let p11=p1.finally(()=>console.log('p1 finally')) //p1 finally
let p21=p2.finally(()=>console.log('p2 finally')) //p2 finally
finally也会返回一个全新的Promise,但是与then和catch不同的是,finally返回的Promise在大多数情况下表现为父Promise的传递,当finally返回的是一个被拒绝的Promise,或者是throw了一个错误时,就会返回这个被拒绝的Promise
let p1=Promise.resolve('p1 resolved')
let p2=Promise.reject('p2 rejected')
let p11=p1.finally(()=>'p11')
let p12=p1.finally(()=>Promise.resolve('p12 resolved'))
let p13=p1.finally(()=>undefined)
let p14=p1.finally(()=>{throw 'p14 error'})
let p21=p2.finally(()=>'p21')
let p22=p2.finally(()=>Promise.reject('p22 rejected'))
let p23=p2.finally(()=>undefined)
let p24=p1.finally(()=>{throw 'p14 error'})
setTimeout(console.log,0,p11) //Promise {<fulfilled>: 'p1 resolved'}
setTimeout(console.log,0,p12) //Promise {<fulfilled>: 'p1 resolved'}
setTimeout(console.log,0,p13) //Promise {<fulfilled>: 'p1 resolved'}
setTimeout(console.log,0,p14) //Promise {<rejected>: 'p14 error'}
setTimeout(console.log,0,p21) //Promise {<rejected>: 'p2 rejected'}
setTimeout(console.log,0,p22) //Promise {<rejected>: 'p22 rejected'}
setTimeout(console.log,0,p23) //Promise {<rejected>: 'p2 rejected'}
setTimeout(console.log,0,p24) //Promise {<rejected>: 'p14 error'}
还有一种情况会返回一个待定态的Promise,就是当返回值是一个new Promise并且这个Promise没有完成时,就会返回一个待定态的Promise,当然,如果这个Promise只是暂时没有完成,但终究会完成的话,那么就会按照上面的情况进行处理。
let p1=Promise.resolve('p1 resolved')
let p11=p1.finally(()=>new Promise(()=>{}))
let p12=p1.finally(()=>new Promise((resolve,reject)=>{setTimeout(()=>resolve('p12 resolved'),500)}))
let p13=p1.finally(()=>new Promise((resolve,reject)=>{setTimeout(()=>reject('p13 rejected'),500)}))
setTimeout(console.log,0,p11) //Promise {<pending>}
setTimeout(console.log,0,p12) //Promise {<pending>}
setTimeout(console.log,0,p13) //Promise {<pending>}
//大约1s后
setTimeout(console.log,1000,p12) //Promise {<fulfilled>: 'p1 resolved'}
setTimeout(console.log,1000,p13) //Promise {<rejected>: 'p13 rejected'}
Promise代码的执行顺序
Promise中的执行顺序是由讲究的,当生成一个new Promise时,这个新的Promise内部的代码是同步执行的,而这个Promise的then方法一定是之前的Promise完成后才会执行,并且,如果同时外部有一个同步代码同时执行,那么then方法的执行时间一定会在同步代码之后。
并且,如果在代码排列顺序上先执行了then方法,也会是一样的结果,因为then方法一定需要等之前Promise的同步代码以及其他的同步代码完成后,才会执行。
let p1=new Promise((resolve)=>{
func = function(){
console.log('1')
resolve()
console.log('2')
}
})
let p2=p1.then(()=>{console.log( '3' )})
func()
console.log('4')
//1
//2
//4
//3
并且,同级的处理程序会按级别依次进行,无论是then,catch还是finally都是如此
let p1=Promise.resolve()
let p2=Promise.reject()
let p3=p1.then(()=>console.log('1'))
.then(()=>console.log('2'))
.finally(()=>console.log('3'))
let p4=p2.then(null,()=>{console.log('11');throw 'error'})
.catch(()=>console.log('12'))
.finally(()=>console.log('13'))
//1
//11
//2
//12
//3
//13