接着上面的primise的基础;
在Promise实例生成过后;可调用then方法;进行相应的状态回调;
const promise=new Promise((resolve,reject)=>{
//其他操作
if(成功){
resolve(value);将状态改为成功的状态
}else{
reject(error);将状态改为失败;
}
});
接着调用then方法;
promise.then((valuse)=>{
//成功的回调
},(error)=>{
//失败的回调;
});
可以看出来;then的函数接受两个参数;首先一个就是在resolve的状态下的回调函数;第二个是rejected的状态回调;第二个函数不是必传的;
另外就是then方法执行的时间是在Promise实例状态在resolve或者reject的时候才会执行then里面的方法;并且可以接受resolve(value)中的value参数;
看一个例子:
let laodeImageAsync=(url)=>{
return new Promise(()=>{
const image=new Image();
image.onload=function(){
resolve(image);
};
image.onerror=()=>{
reject(new Error('Could not load image at '+ url));
};
return image.src=url;
})
};
也就是在处理完成后;改变promise的状态;然后做相应的操作;
两个Promise的回调问题
如果在调用Promise的状态改变的后;会把参数给到回调函数;resolve函数出了正常的值以外;还有可能是另外一个Promise的实例;
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)
})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
p2
.then(result => console.log(result))
.catch(error => console.log(error))
上面代码中,p1是一个 Promise,3 秒之后变为rejected。p2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。
注意,调用resolve或reject并不会终结 Promise 的参数函数的执行。
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2
// 1
上面代码中,调用resolve(1)以后,后面的console.log(2)还是会执行,并且会首先打印出来。这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。
then catch
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
其实在promise中rejected的状态就是catch;
finally;
finally方法用于指定不管Promise对象最后状态如何;都会执行操作;该方法是ES2018引入的标准
promise
.finally(() => {
// 语句
});
// 等同于
promise
.then(
result => {
// 语句
return result;
},
error => {
// 语句
throw error;
}
);
上面代码中,如果不使用finally方法,同样的语句需要为成功和失败两种情况各写一次。有了finally方法,则只需要写一次。
Promise.all();
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.all([p1, p2, p3]);
p1,p2,p3都是Promise实例;p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
// 生成一个Promise对象的数组
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
Promise.race();
Promise.race()方法是将多个Promise实例包装为一个实例;
const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
Promise.race方法的参数与Promise.all方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理
网友评论