浅析Promise-2

96 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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对象抛出的错误不会被传递到代码外层,即不会有任何反应。 捕获.JPG   在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();