持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
2、Promise的几种方法
(1)Promise.then():用于注册状态变为fulfilled或者reject时的回调函数,接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。then()方法返回的是一个新的Promise实例,因此可以采用链式写法。
const promise = new Promise((resolve, reject) => {
resolve('fulfilled'); // 状态由 pending => fulfilled
});
promise.then(result => {
console.log(result); // 'fulfilled'
}, reason => { // onRejected 不会被调用
})
(2)Promise.catch():在链式写法中可以捕获then中发送的异常。
一般来说,不要在then()里面定义rejected状态的回调函数(即then的第二个参数),而应该使用catch()方法。理由是catch()方法可以捕获前面then()方法执行中的错误,也更接近同步的写法(try/catch)。
和传统的try/catch代码块不同的是,如果没有使用catch()方法指定错误处理的回调函数,Promise对象抛出的错误不会被传递到代码外层,即不会有任何反应。
在someAsyncThing函数中产生Promise对象,内部有语法错误,浏览器运行到这一步会打印错误,但是并不会退出进程、终止脚本执行,2s后还是输出123。也就是说Promise内部的错误并不会影响到Promise外部的代码,即“Promise会吃掉错误”。
(3)Promise.all():可以将多个Promise实例包装成一个新的Promise实例。
多个Pomise任务同时执行,如果全部执行成功,则以数组的方式返回所有Promise任务的执行结果。如果有一个Promise任务rejected,则只返回第一个rejected任务的结果。
Promise.all([p1,p2,p3])接受一个数组作为参数,数组中的p1,p2,p3都是promise实例。
let p1=new Promise((resolve,reject)=>{
resolve('p1成功');
})
let p2=new Promise((resolve,reject)=>{
resolve('p2成功');
})
let p3=Promise.reject('p3失败');
Promise.all([p1,p2]).then((res)=>{
console.log(res);// ['p1成功','p2成功']
}).catch((err)=>{
console.log(err);
})
Promise.all([p1,p2,p3]).then((res)=>{
console.log(res);//p3失败
}).catch((err)=>{
console.log(err);
})
注意: Promise.all()获得的成功结果的数组里面的数据顺序与Promise.all()接收参数的顺序是一致的,即P1的结果在前,即使P1的结果获取的比P2晚。 这带了一个很大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个异步请求要求按照发送的顺序获取数据,使用Promise.all()可以解决这个问题。
(4)Promise.race():race赛跑的意思,多个Prromise任务同时执行,返回最先执行结束的Promise任务的结果,不管这个Promise结果是成功还是失败。 注意:Promise.race在第一个Promise对象变为fulfilled之后,并不会取消其他promise对象的执行。只是只有先完成的Promise才会被Promice.race后面的then()处理,其他promise还是在执行的,只不过不会进入到promise.race后面的then里。
let p1=new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('p1成功');
},2000)
})
let p2=new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('p2成功');
})
},500)
Promise.race([p1,p2]).then((res)=>{
console.log(res);//p2成功
}).catch((err)=>{
console.log(err);
})
3、实现Promise.all()的内部原理
function promiseAll(promises){
if(!Array.isArray(promises)){
throw new TypeError('argument must be array');
}
return new Promise((resolve,reject)=>{
let len=promises.length;
let index=0;
var res=[];
for(let i=0;i<len;i++){//注意定义为let,保留当前的i
promises[i].then((data)=>{//执行参数中的promise实例
index++;
res[i]=data;//把每一个promise的执行成功结果放入数组中 不能用push()方法,保证返回的顺序
if(index==len){//说明所有promise都执行成功
return resolve(res);
}
},function(err){
return reject(err);
})
}
})
}
var a1=Promise.resolve(1);
var a2=Promise.resolve(2);
var a3=new Promise((resolve,reject)=>{
resolve('a3');
})
promiseAll([a1,a2,a3]).then(function(res){
console.log(res);//[1,2,'a3']
}).catch(function(err){
console.log(err);
})
4、实现Promise.race()的内部原理
function Race(promise){
return new Promise((resolve,reject)=>{
for(let i=0;i<promise.length;i++){
promise[i].then(resolve,reject);
}
})
}
var p1=new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('2');
},2000)
})
var p2=new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('3');
},1000)
})
Race([p1,p2]).then(function(val){
console.log(val);//3
})
5、Promise应用:红绿灯问题
题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次;如何让三个灯不断交替重复亮灯?(用 Promse 实现)
function red(){
console.log('red');
}
function green(){
console.log('green');
}
function yellow(){
console.log('yellow');
}
var light=function(timer,func){
return new Promise(function(resolve,reject){
setTimeout(function(){
func();
resolve();
},timer)
})
}
var step=function(){//then()链式
Promise.resolve().then(function(){
return light(3000,red);
}).then(function(){
return light(2000,green);
}).then(function(){
return light(1000,yellow);
}).then(function(){
step();
})
}
step();