Promise是一种异步编程的选择,它既可以像事件和回调函数一样指定稍后执行的代码,也可以明确指示代码是否成功执行。
Promise生命周期
操作未完成是处于进行中(pending)的状态,也是未处理(unsettled)状态。一旦操作执行结束,Promise处于已处理(settled)状态,异步操作成功处于fulfilled状态,异步操作未成功处于rejected状态。内部属性[[PromiseState]]用来表示这三种状态。
then()
只有当Promise状态改变时,可以通过then()方法检测Promise的状态。
接受两个参数:当状态变成fulfilled时要调用的函数;当状态变成rejected时要调用的函数
let promise=readFile("example.txt");
promise.then(function(content){
//fulfilled
console.log(content)
},function(err){
//rejected
console.log(err);
});
//fulfilled
promise.then(function(content){
console.log(content)
});
//rejected
promise.then(null,function(err){
console.log(err)
})
catch()
相当于只给其传入拒绝处理程序的then()方法
promise.catch(function(err){
console.log(err)
})
总结:
- then()和catch()一起使用才能更好地处理异步操作结果
- 如果一个Promise处于已处理状态,在那之后添加的新的处理程序仍可以执行
创建未完成的Promise
用Promise函数可以创建新的Promise,因为Promise执行器具有动态性。构造函数只接受一个参数:包含初始化Promise代码的执行器函数。执行器接受两个参数:resolve()函数和reject()函数。执行器成功调用resolve()函数,失败调用reject()函数。
创建已处理的Promise
Promise.resolve()
只接受一个参数并返回一个完成态的Promise
Promise.reject()
与Promise.resolve()很像,但是用来创建已拒绝的Promise
非Promise的Thenable对象
拥有then()方法并且接受resolve和reject两个参数的普通对象就是非Promise的Thenable对象。
可以通过调用Promise.resolve()方法将Thenable对象转换成一个已完成的Promise。
总结:
- 有了Promise.resolve()方法和Promise.reject()方法,可以更轻松地处理非Promise的Thenable对象。
- 如果不确定某个对象是不是Promise对象,那么可以根据预期的结果将其传入Promise.resolve()方法或Promise.reject()方法中,如果它是Promise对象,则不会有任何变化。
全局的Promise拒绝处理
Node.js环境的拒绝处理
处理Promise拒绝时会触发process对象上的两个事件:
- unhandledRejection 在一个事件循环中,当Promise被拒绝,并且没有提供拒绝处理程序时,触发该事件。接收两个参数:拒绝原因(通常是一个错误对象)和被拒绝的Promise。
- rejectionHandled 在一个事件循环后,当Promise被拒绝,若拒绝处理程序被调用,触发该事件。接收一个参数:被拒绝的Promise
识别那些被拒绝却又没被处理过的Promise
浏览器环境的拒绝处理
虽然这些事件是在window对象上触发的,但是实际上与Node.js的完全等效。
- unhandledrejection 在一个事件循环中,当Promise被拒绝,并且没有提供拒绝处理程序时,触发该事件。
- rejectionhandled 在一个事件循环后,当Promise被拒绝,若拒绝处理程序被调用,触发该事件。
事件处理程序接受一个有以下属性的事件对象作为参数:
- type 事件名称(“unhandledrejection”或“rejectionhandled”)
- promise 被拒绝的Promise对象
- reason 来自Promise的拒绝值(两个事件都可以使用拒绝值)
串联Promise
每次调用then()或catch()方法时实际上创建并返回了另外一个Promise,只有当第一个Promise被完成或被拒绝之后,第二个才会被解决。
let p1=new Promise(function(resolve,reject){
resolve(42);
})
p1.then(function(value){
console.log(value);
}).then(function(){
console.log("finish");
})
Promise链捕获错误
Promise链可以用来捕获错误
let p1 = new Promise(function(resolve, reject) {
resolve(42);
})
p1.then(function(value) {
throw new Error("boom")
}).catch(function(error) {
console.log(error.message);
})
p1的完成处理程序抛出了一个错误,链式调用第二个Promise的catch()方法后,可以通过他的拒绝处理程序接收这个错误。
链式Promise调用可以感知到链中其他Promise的错误。
Promise链的返回值
Promise链可以给下游Promise传递数据。当从执行器resolve()处理程序到Promise完成处理程序可进行数据传递,那么在完成处理程序中再指定一个返回值,可以沿着这条链继续传递数据。拒绝处理程序也是如此。
在必要时,即使其中一个Promise失败也可以恢复整条链的执行。
在Promise链中返回Promise
调用完成处理程序
let p1=new Promise(function(resolve,reject){
resolve(42);
})
let p2=new Promise(function(resolve,reject){
resolve(43);
})
p1.then(function(value){
console.log(value);
return p2;
}).then(function(){
console.log(value);
})
调用拒绝处理程序
let p1=new Promise(function(resolve,reject){
resolve(42);
})
let p2=new Promise(function(resolve,reject){
reject(43);
})
p1.then(function(value){
console.log(value);
return p2;
}).catch(function(){
console.log(value);
})
调用非Thenable对象
let p1=new Promise(function(resolve,reject){
resolve(42);
})
p1.then(function(value){
console.log(value);
let p2=new Promise(function(resolve,reject){
resolve(43);
})
return p2;
}).then(function(){
console.log(value);
})
响应多个Promise
Promise.all()
Promise.all()只接受一个参数并只返回一个Promise,该参数是一个含有多个监视Promise的可迭代对象(数组),只有当可迭代对象中所有的Promise都被解决后,返回的Promise才会被解决。
let p1 = new Promise(function(resolve,reject){
resolve(42);
})
let p2 = new Promise(function(resolve,reject){
resolve(43);
})
let p3 = new Promise(function(resolve,reject){
resolve(44);
})
let p4 = Promise.all([p1, p2, p3]);
p4.then(function(value) {
console.log(value) //[42,43,44]
})
只要有一个被拒绝,返回的Promise没等所有的Promise都完成就立刻被拒绝,所以拒绝处理程序总是接收一个值而非一个数组。
let p1 = new Promise(function(resolve,reject){
resolve(42);
})
let p2 = new Promise(function(resolve,reject){
reject(43);
})
let p3 = new Promise(function(resolve,reject){
resolve(44);
})
let p4 = Promise.all([p1, p2, p3]);
p4.then(function(value) {
console.log(value) //43
})
Promise.race()
它也接收只接受一个参数并只返回一个Promise,但是只要有一个Promise被解决返回的Promise就被解决,无需等到所有Promise都被完成
let p6 = Promise.resolve(46);
let p1 = new Promise(function(resolve, reject) {
resolve(42);
})
let p2 = new Promise(function(resolve, reject) {
reject(43);
})
let p3 = new Promise(function(resolve, reject) {
resolve(44);
})
let p5 = Promise.resolve(45);
let p4 = Promise.race([p1, p2, p3, p5, p6]);//关键在于数组的排序
p4.then(function(value) {
console.log(value) //42
})