基本用法
Promise是一种异步解决方案,最早由社区提出并实现,后来写进了es6规范。
ES6规定,Promise对象是一个构造函数,用来生成Promise实例
Promise是异步编程的一种解决方案,它有三种状态,分别是pending-进行中、resolved-已完成、rejected-已失败
当Promise的状态由pending转变为resolved或rejected时,会执行相应的方法,并且状态一旦改变,就无法再次改变状态,这也是它名字promise-承诺的由来
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise 实例生成以后,可以用then 方法分别指定resolved状态和rejected状态的回调函数。
// 方法1
let promise = new Promise ( (resolve, reject) => {
if ( success ) {
resolve(a) // pending ——> resolved 参数将传递给对应的回调方法
} else {
reject(err) // pending ——> rejectd
}
} )
// 方法2
function promise () {
return new Promise ( function (resolve, reject) {
if ( success ) {
resolve(a)
} else {
reject(err)
}
} )
}复制代码
注意:实例化的Promise对象会立即执行
Promise.prototype.then() VS Promise.prototype.catch()
.then()方法使Promise原型链上的方法,它包含两个参数方法,分别是已成功resolved的回调和已失败rejected的回调
promise.then(
() => { console.log('this is success callback') },
() => { console.log('this is fail callback') }
)
复制代码
.catch()的作用是捕获Promise的错误,与then()的rejected回调作用几乎一致。但是由于Promise的抛错具有冒泡性质,能够不断传递,这样就能够在下一个catch()中统一处理这些错误。同时catch()也能够捕获then()中抛出的错误,所以建议不要使用then()的rejected回调,而是统一使用catch()来处理错误
promise.then(
() => { console.log('this is success callback') }
).catch(
(err) => { console.log(err) }
)
复制代码
同样,catch()中也可以抛出错误,由于抛出的错误会在下一个catch中被捕获处理,因此可以再添加catch()
使用rejects()方法改变状态和抛出错误 throw new Error() 的作用是相同的
当状态已经改变为resolved后,即使抛出错误,也不会触发then()的错误回调或者catch()方法
then() 和 catch() 都会返回一个新的Promise对象,可以链式调用
promise.then(
() => { console.log('this is success callback') }
).catch(
(err) => { console.log(err) }
).then(
...
).catch(
...
)复制代码
案例
function jiaowaimai() {
return new Promise((resolve,reject) => {
let result = zuofan();
if(result == "菜做好了") {
resolve("哈哈 我们已经做好了")
}else {
reject('不好意思,我们还没有做好')
}
})
}
function zuofan() {
return "菜做好了"
}
jiaowaimai()
.then((res)=>{
console.log(res)//哈哈 我们已经做好了
})
.catch(res => console.log(res))复制代码
function jiaowaimai() {
return new Promise((resolve,reject) => {
let result = zuofan();
if(result == "菜做好了") {
resolve("哈哈 我们已经做好了")
}else {
reject('不好意思,我们还没有做好')
}
})
}
function zuofan() {
return "没做好"
}
jiaowaimai()
.then((res)=>{
console.log(res)
})
.catch(res => console.log(res))//不好意思,我们还没有做好
复制代码
Promise实例的异步方法和then()中返回promise有什么区别?
// p1异步方法中返回p2
let p1 = new Promise ( (resolve, reject) => {
resolve(p2)
} )
let p2 = new Promise ( ... )
// then()中返回promise
let p3 = new Promise ( (resolve, reject) => {
resolve()
} )
let p4 = new Promise ( ... )
p3.then(
() => return p4
)
复制代码
p1异步方法中返回p2
p1的状态取决于p2,如果p2为pending,p1将等待p2状态的改变,p2的状态一旦改变,p1将会立即执行自己对应的回调,即then()中的方法针对的依然是p1
then()中返回promise
由于then()本身就会返回一个新的promise,所以后一个then()针对的永远是一个新的promise,但是像上面代码中我们自己手动返回p4,那么我们就可以在返回的promise中再次通过 resolve() 和 reject() 来改变状态
Promise的其他api
Promise.resolve() / Promise.reject()
用来包装一个现有对象,将其转变为Promise对象,但Promise.resolve()会根据参数情况返回不同的Promise:
参数是Promise:原样返回
参数带有then方法:转换为Promise后立即执行then方法
参数不带then方法、不是对象或没有参数:返回resolved状态的Promise
Promise.reject()会直接返回rejected状态的Promise
Promise.all()
参数为Promise对象数组,如果有不是Promise的对象,将会先通过上面的Promise.resolve()方法转换
var promise = Promise.all( [p1, p2, p3] )
promise.then(
...
).catch(
...
)
复制代码
当p1、p2、p3的状态都变成resolved时,promise才会变成resolved,并调用then()的已完成回调,但只要有一个变成rejected状态,promise就会立刻变成rejected状态
Promise.race()
var promise = Promise.race( [p1, p2, p3] )
promise.then(
...
).catch(
...
)
复制代码
“竞速”方法,参数与Promise.all()相同,不同的是,参数中的p1、p2、p3只要有一个改变状态,promise就会立刻变成相同的状态并执行对于的回调
Promise.done() / Promise. finally()
Promise.done() 的用法类似 .then() ,可以提供resolved和rejected方法,也可以不提供任何参数,它的主要作用是在回调链的尾端捕捉前面没有被 .catch() 捕捉到的错误
Promise. finally() 接受一个方法作为参数,这个方法不管promise最终的状态是怎样,都一定会被执行