目录
1、Promise对象是一个构造函数,用来生成Promise的实例。
2、Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。
3、在Promise实例中调用resolve()或者reject(),应该在前面加上return这样Promise的使命就完成了,后序的操作就不会执行。
一、含义:
是一个对象,是异步编程的一种解决方案,就是一个容器里面保存着一个异步操作的结果。
二、Promise对象的特点:
1、对象的状态不受外界影响。
Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)
只有异步操作的结果,可以决定当前是哪一种状态。
2、一旦状态改变、就不会再变,任何时候都可以得到这个结果。
Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要两种情况发生了,状态就凝固了,不会再变了。
3、避免了层层嵌套的回调函数,解决回调地狱的问题。
Promise对象支持链式调用,提供统一的接口,使得控制异步操作更加容易。
三、基本用法:
1、Promise对象是一个构造函数,用来生成Promise的实例。
接受一个函数作为参数,该函数的两个参数分别是resolve和reject,他们是两个函数。
resolve函数作用:将Promise对象的状态从“未完成”变为“成功”,pending-->resolved。在异步操作成功时调用,将异步操作的结果作为参数传递出去。
rejecte函数作用:将Promise对象的状态从“未完成”变为“失败”,pending-->rejected。在异步操作失败时调用,将异步操作的结果作为参数传递出去。
resolve和reject函数都可以接受参数,这些参数会被返回给回调函数。reject函数的参数通常是Error对象的实例,resolve函数的参数可以是正常值也可以是Promise实例。
var test = new Promise((resolve,reject) => {
if(//异步操作成功){
resolve(value);
}else{
reject(error);
}
})
2、Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。
第一个回调函数是Promise对象的状态变为Resolved时调用,第二个是Promise状态为Rejected时调用(可选)。
test.then((value)=>{
//success
},(error) =>{
//failure
})
3、在Promise实例中调用resolve()或者reject(),应该在前面加上return这样Promise的使命就完成了,后序的操作就不会执行。
var aa = new Promise((resolve,rejected)=>{
return resolve(2);
console.log(4); // 不会打印 因为return后Promise的使命就完成了
}).then(r=>{
console.log(r);//会打印 2
});
var bb = new Promise((resolve,rejected)=>{
resolve(3);
console.log(1); //首先打印1 因为在Promise构造器内 是同步执行的
}).then(r=>{
console.log(r); //接着打印3
});
四、Promise.prototype.then()
then方法的作用:为Promise实例添加状态改变时的回调函数。
第一个回调函数是Promise对象的状态变为Resolved时调用,第二个是Promise状态为Rejected时调用(可选)。
then方法返回的是一个新的Promise实例,可以采用链式的写法。若前一个返回值是Promise对象,那么后一个回调函数就会等待该Promise对象的状态发生改变。
五、Promise.prototype.catch()
用于指定发生错误时的回调函数。一般来说不要在then方法中定义Rejected状态的回调函数(then的第二个参数),而应总是使用catch方法。
Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。错误总会被下一个catch语句捕获。
注意的是catch方法返回的还是一个promise对象。
六、Promise.all()
用于将多个Promise实例包装成一个新的Promise 实例。状态由参数(都是Promise对象的实例)决定,都为resolved才是resolved否则为rejected。
如果参数自身定义了catch方法,那么rejected的时候不会触发Promise.all()的catch方法。
const p1 = new Promise((resolve,reject)=>{
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve,reject) => {
throw new Error('报错了');
})
.then(result => console.log(result))
.catch(e => console.log(e))
Promise.all([p1,p2])
.then(result => console.log(result)) // [hello,undefined]
.catch(e => console.log(e));
//如果作为参数的Promise实例自身定义了catch方法,那么它被rejected的时候不会触发Promise.all()的catch方法
const p1 = new Promise((resolve,reject)=>{
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve,reject) => {
throw new Error('报错了');
})
.then(result => console.log(result))
Promise.all([p1,p2])
.then(result => console.log(result))
.catch(e => console.log(e)); //Error: 报错了
七:Promise.race()
同样将Promise实例包装成一个新的Promise实例。
只要参数中有一个实例率先改变状态,P的状态就跟着改变。那个率先改变的Promise实例的返回值就传递给p的回调函数。
八:Promise.resolve()
将现有对象转为Promise对象。
var jsPromise = Promise.resolve('foo');
resolve参数的情况:
1、参数是一个Promise实例:
原封不动的返回这个实例。
2、参数是一个具有then方法的对象:
会将这个对象转为Promise对象,然后立即执行对象的then方法
3、参数不是具有then方法的对象或者根本不是对象:
Promise.resolve()方法会返回一个新的Promise对象,状态为Resolved
4、不带有任何参数:
直接返回一个Resolved状态的Promise对象。Resolve的Promise对象是在本轮“事件循环”结束时开始的。
setTimeout(function(){
console.log('three');
},0);
Promise.resolve().then(function(){
console.log('two');
})
console.log('one');
九、Promise.reject():
会返回一个新的Promise实例,状态位Rejected。
Promise.reject()方法的参数会原封不动地作为reject的理由,变为后续方法的参数。
十、自定义方法:
1、done():相当于异常穿透
异常穿透:前面任何操作出了一场,都会传到最后失败的回调中处理。
Promise最后一个方法抛出的错误可能会捕捉不到,我们定义一个doen方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。
Promise.prototype.done = (onFulfilled,onRejected) => {
this.then(onFulfilled,onRejected)
.catch(function(reason){
// 抛出一个全局错误
setTimeout(()=>{throw reason},0);
})
}
2、finall():
用于指定不管Promise对象最后状态如何都会执行的操作,它接收一个回调函数作为参数,该函数不管怎么样都必须执行。
Promise.prototype.finally = function(callback){
let p = this.constructor;
return this.then(
value => p.resolve(callback().then(()=>value)),
reason => p.resolve(callback().then(()=>{throw reason})
)
)
}
十一:如何中断Promise链?
中断Promise链:当使用Promise的then链式调用时,在中间中断,不再调用后面的回调函数。
解决办法:在回调函数中返回一个pendding状态的promise对象。
new Promise((resolve,reject) => {
reject(1);
}).then(
value => {
console.log('onResolved1()',value);
return 2;
}
).then(
value => {
console.log('onResolved2()',value);
return 3;
}
//相当于 reason => {throw reason} 为什么写大括号?因为throw的左边不能有return
).then(
value => {
console.log('onResolved3()',value);
return 4;
}
).catch(
reason => {
console.log("失败"+reason);
return new Promise(()=>{});
},
//中断Promise链
).then(
value => {
console.log('onResolved2()',value);
},
//相当于 reason => {throw reason}
reason => {
console.log("失败2"+reason);
}
)
内容参考《Es6标准入门》