Promise 、async 、await 简单学会


提示:以下是本篇文章正文内容,下面案例可供参考

1.回调函数

在学习promise之前,大家先要知道什么是回调函数?
回调函数其实就是把一个函数当做参数传递给另一个函数:

function start(callBlak){
	  let i = 1;
	  let time = null;
	  time =  setInterval(function(){
	      i--;
	      if( i < 0  ){
	          clearInterval(time)
	          callBlak? callBlak() : '';
	      }
	 },1000) 
}
start(function(){ console.log('hello world'); })

2.回调地狱

在某些逻辑下,使用回调函数可能造成恐怖的回调地狱!
如经典的Ajax的success就是回调函数,只有得到一个接口服务器返回的某个信息,我们才能拿这这个信息去做新的请求,循环往复,代码会变得十分的恐怖!
例子:(可以略过,大概理解上面的话就可以了,后面会讲解决方案)

$.ajax({
     url:'http://www.xxx.com/index.php/index/goods/userinfo',
     method:'post',
     data:{
         username:'a123123'
     },
     success:res=>{
         $.ajax({
             url:'http://www.xxx.com/index.php/index/goods/orderinfo',
             method:'post',
             data:{
                 id:res.info.user_id
             },
             success:userres=>{
                 $.ajax({
                     url:'http://www.xxx.com/index.php/index/goods/goodsinfo',
                     method:'post',
                     data:{
                         id:userres.info.goods_id
                     },
                     success:goosres=>{
                         console.log(goosres);
                     }
                 })
             }
         })
     }
 })

3.同步异步

同步:等待上一同步任务执行完毕,才执行下一个同步任务
异步:等待所有同步任务执行完毕,再执行异步任务
常见的异步操作:setIntervalval、setTimeout、ajax
所有的同步任务都在主线程中执行,在主线程之外有一个任务队列,所有的异步任务都会进入任务队列,等待同步任务执行完毕之后执行
在这里插入图片描述

4.Promise

Promise对象就是专门用来解决异步问题的。

Promise有三个状态:pending(准备状态)、fulfilled(成功状态)、rejected(失败状态)

Promise还有两个方法:resolve() 、 reject(),通过这两个方法可以改变状态。

		pending(准备状态) -> resolve() -> fulfilled(成功状态)
		pending(准备状态) -> reject() -> rejected(失败状态)

并且,当改变发生之后,状态就会定型,后续通过方法可以获取对应状态的结果。
举个例子:

function pro(){
    return new Promise((reolve,reject)=>{
         console.log('异步程序'); // 模拟ajax
         if(true){
             reolve('成功')
         }else{
             reject('失败')
         }
     })
 }
 pro().then(function(res){
 	// res为 reolve 返回的值
    console.log(res);
 })

new Promise生成promise实例之后,可以通过 then 方法来指定resolve和reject的回调函数
then方法中可以继续 return 一个promise对象,然后返回值就是这个promise对象
这里有个细节大家需要注意一下,就是new Promise构建promise对象会立即执行,所以一般会把new Promise封装在一个函数中,保证只有调用时才执行。

最后则是关于promise错误状态的处理(可能出现的reject状态)
解决方法就是catch,在最后用catch捕获错误,返回错误信息

function p1(){
     let p = new Promise((resolve,reject) => {
         setTimeout(() => {
             resolve({a:1,b:2})
         },1000)
     })
     return p;
 }
 function p2(){
     let p = new Promise((resolve,reject) => {
         setTimeout(() => {
             resolve('hello world')
         },1000)
     })
     return p;
 }
 
 p1().then((res) => {
     return p2();
 }).then((res) => {
     console.log(res)
 }).catch((err) => {
     console.log("err",err)
 })

catch只需要在最后写一次,无论中途哪里出现reject状态,都会进入catch。

下面简单说一下,Promise对象的几个方法

Promise.finally()

finally()方法用于指定不管Promise对象最后的状态如何,都会执行的操作。
finally()方法不接收任何参数,并且与Promise对象的状态无关,所以finally方法中执行的逻辑应该是跟promise对象逻辑无关的一个逻辑操作。

Promise.all()

Promise.all()方法接收多个promise实例作为参数,这样就可以把异步请求封装到promise实例中,然后同时发起请求。
在实际应用中,同时并发的操作并不常见,而且还很容易出现问题。
因为只要出现一次reject,最后会进入catch方法,并且只得到reject的结果。

这里直接上解决方法:
给每个参数promise实例添加一个catch方法,当有错误发生时,错误会进入自身的catch方法,并且自身catch方法return的数据,将作为最终结果进入到all方法的then中。

let p1 = new Promise((reolve,reject)=>{
    if(true){
         reolve('成功1')
     }else{
         reject('失败1')
     }
 }).catch(err=>err)
 let p2 = new Promise((reolve,reject)=>{
     if(false){
         reolve('成功2')
     }else{
         reject('失败2')
     }
 }).catch(err=>err)
 let p3 = new Promise((reolve,reject)=>{
     if(false){
         reolve('成功3')
     }else{
         reject('失败3')
     }
 }).catch(err=>err)
 
 Promise.all([p1,p2,p3]).then((res)=>{
     console.log(res);
 }).catch((err)=>{
     console.log(err);
 })

Promise.race()

跟 Promise.all()方法一样,同时执行多个实例,哪个先确定状态,race方法就以哪个状态为主

let p1 = new Promise((reolve,reject)=>{
     setTimeout(()=>{
         if(true){
         reolve('成功1')
         }else{
             reject('失败1')
         }
     },3000)
 }).catch(err=>err)
 let p2 = new Promise((reolve,reject)=>{
     setTimeout(()=>{
         if(false){
         reolve('成功2')
         }else{
             reject('失败2')
         }
     },2000)
 }).catch(err=>err)
 let p3 = new Promise((reolve,reject)=>{
     setTimeout(()=>{
         if(false){
         reolve('成功3')
         }else{
             reject('失败3')
         }
     },1000)
 }).catch(err=>err)
 Promise.race([p1,p2,p3]).then((res)=>{
     console.log(res);
 }).catch(err=>console.log(err))

Promise.allSettled()

Promise.allSettled()方法专门用来处理Promise.all()出错的情况。不管参数Promise实例的状态如何,最终都进入到成功结果(then)中去。只是结果中通过特定的值方式表明成功或者失败情况。

let p1 = new Promise((reolve,reject)=>{
    return Math.random() > 0.5 ? reolve('成功1') : reject('失败1');
 })
 let p2 = new Promise((reolve,reject)=>{
     return Math.random() > 0.5 ? reolve('成功2') : reject('失败2');
 })
 let p3 = new Promise((reolve,reject)=>{
     return Math.random() > 0.5 ? reolve('成功3') : reject('失败3');
 })
 Promise.allSettled([p1,p2,p3]).then((res)=>{
     console.log(res);
 }).catch(err=>console.log(err))

5.async

async可以将普通函数转换成Promise实例!

 async function abc(){

 }
 let res = abc();
 console.log( res ); // Promise对象

async函数的返回值将作为Promise实例的resolve的结果,这里就是操作Promise对象的操作了!

 async function abc(){
     return 'hello world'
 }
 abc().then(function(res){
     console.log(res);
 })

6.await

await就是等待的意思,只可以用在async函数中(用在普通函数中会报错),他一般用来修饰一个Promise对象,等待promise的状态确定之后,等待状态才会结束! 并且await命令会返回他修饰的promise对象的resolve值
注意:只会返回resolve值,reject值会终止async函数

async function abc(){
    let a =  await new Promise(function(reolve,reject){
         setTimeout(function(){
             console.log('异步任务');
             reolve('成功')
         },3000)  
     })
     console.log('同步任务');
 }
 abc()

大家可以复制上面的例子看一下控制台。
通过await已经实现了让同步等待异步的操作,变相的把一个异步任务变成了同步任务

现在我们回头看一下一开始的回调地狱例子,用async、await来解决会变得十分简单

let url1 = 'http://www.xxx.com/index.php/index/goods/userinfo';
    let url2 = 'http://www.xxx.com/index.php/index/goods/orderinfo';
    let url3 = 'http://www.xxx.com/index.php/index/goods/goodsinfo';

    function getUser(userUrl,userData){
        return new Promise((reolve,reject)=>{
            $.ajax({
                url:userUrl,
                method:'post',
                data:userData,
                success:(res)=>{
                    reolve(res)
                },
                error:(err)=>{
                    reject(err)
                }
            })
        })
    }

    async function start(){
        let Userid = await getUser(url1,{username:'a123123'})
        let orderid = await getUser(url2,{id:Userid.info.user_id})
        let goodsinfo = await getUser(url3,{id:orderid.info.goods_id})
        console.log(goodsinfo);
    }
    start().catch(err=>console.log(err))

由于我用的是本地模拟服务器,所以你们看不了结果了,我们主要还是看逻辑。
这里的执行逻辑会变成,大家对程序最开始的理解,因为ajax已经被变成了同步任务,所以逻辑就变成了,一行代码结束,下一行代码才会开始执行。

最后说一下:关于async函数的错误状态处理
在async函数中,如果函数体中出现程序错误(变量未定义、方法名字写错…)或者await 后边的promise对象 返回reject状态,都会终止async函数的运行,进入async函数的catch方法中(相当于promise状态变为reject失败状态)。

解决方法:给每个Promise对象添加 catch() 方法,或者直接用 try/catch方法,篇幅有限,这里先暂时不表。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值