ES8新特性之async函数与await表达式(常见疑惑解答)

说明:在学习了async和await后,很多人往往不知道这两个人是干什么的,对于这两个重要角色的使用方式和原理都比较模糊,下面为大家介绍这两个角色的语法,后面附有两个小例子,能够让大家明白async和await的作用以及使用场景。

简介:async和await两种语法结合可以使得异步代码像同步代码一样使用。
关于async函数:
简介:实质上就是在普通函数前添加上async关键字进行修饰的函数。
此种函数被称为async函数,且其返回值必定为一个Promise对象。
Promise对象的状态依据async函数的返回值情况决定:
1,当async函数的返回值非“Promise对象”时:
函数的返回值为一个成功的Promise对象。
2,当async函数的返回值为Promise对象时:
函数的返回值的Promise对象是否成功由返回值的Promise对象决定
3,当async函数的返回值抛出错误时:
函数的返回值为一个失败的Promise对象。

格式:“ async function 方法名 ( ) { //方法体 } ”
例子

async function func(){
    //方法体
    return new Promise(function(resolve,reject){
        //Promise实例构造函数参数的方法体
        if(xxxx){
            resolve("参输内容");
        }else{
            reject("参数内容");
        }
    })
}
//调用async函数,获取其返回的Promise对象
const promiseFromFunc = func();
promiseFromFunc.then(
    function(resolve){
        //成功时执行的方法体
    },
    function(reject){
        //失败时执行的方法体
    }
)

关于await表达式:
简介:对于await表达式,是有使用的前提条件的,前提条件如下:
1,await必须写在async函数中
2,await修饰的一般为一个Promise对象
3,await返回的是Promise的成功值,相当于Promise中then方法的首参数的函数
即:await所修饰的Promise对象会返回该Promise对象所调用resolve()方法时
所传入resolve()方法中的成功的参数内容。
4,await修饰的promise对象必须由try…catch修饰,以接收Promise的错误值。
即:try…catch会捕捉await所修饰的Promise对象所调用reject()方法时
所传入reject()方法中的失败的参数内容。
(以上几条很重要,请认真看。)

例子:

async function func(){
    
    try{
        //此处可以使整个函数直接返回由await修饰的Promise实例的构造方法的返回值
        //也可以不返回值而使用一个变量接收Promise实例的构造方法的返回值,
        //然后传递给方法体之外的变量。
        
        //写法1
        return await new Promise((resolve,reject)=>{
            //Promise函数体
            //此处根据自定义的条件调用resolve或reject
        
        })
        //写法2
        let a = await new Promise((resolve,reject)=>{
            //Promise函数体
            //此处根据自定义的条件调用resolve或reject
        
        }) 
    }catch(e){
        console.log(e);
    }
}

关于async和await自己的理解:
由于async函数的返回值是一个Promise对象,
这就决定了async函数中的await所修饰的一定是一个Promise对象。
await修饰Promise可达到的效果为:对同步代码实行线程阻塞,
等待Promise实例的构造方法中的resolve()方法或reject()方法执行完毕后,
再执行await之后的同步代码。
(注意:Promise本身不是异步方法,其构造函数也不是异步方法,由await修饰后,
线程会等待Promise执行完毕后才会继续执行之后的代码。当Promise的状态被决定后,
则判定Promise已被执行完毕。)

async和await解决了什么问题?
以一个“异步请求数据不同步”的问题来说明。异步请求数据不同步的问题是指
现需求异步请求数据,将数据渲染至页面上,以一般思路来讲,代码可能如下:

let a = null;//a方法外的一个全局变量,用于作为渲染数据的中间变量
function getNews(){
    //定义一个获取信息的方法,并在该方法下发送异步请求
    $.post('./databaseConn.php',{},function (res){
        if (res !== null){
            res = JSON.parse(res);
            a=res.news_content;//此处给a变量赋值,内容为后台所获取到的信息。
        }
    });
    //此处打印a变量,打印结果为null。
    //原因:因为上面是一个post异步请求代码,而console.log是一个同步代码
    //因此,上述请求代码没有执行完毕,console.log代码就已经执行了
    //因为上述异步请求代码还未执行完毕,故a变量还未被赋值,所以打印结果为null
    console.log(a);
}
getNews();

如果使用async方法配合await表达式即可解决上述问题,则代码如下:

let a = null;//a方法外的一个全局变量,用于作为渲染数据的中间变量

async function getNews(){
    //此为一个async方法
    try{
        //此处使用await修饰Promise对象,可以保证Promise中的
        //异步请求操作执行完毕以后再进行await之后的“同步操作”
        a = await new Promise((resolve,reject)=>{
            $.post('./databaseConn.php',{},function (res){
                if (res !== null){
                    res = JSON.parse(res);
                    // console.log(res.news_content);
                    // a=res.news_content;
                    resolve(res.news_content);
                }
            });
        })
    }catch (e) {
        console.error("错误")
    }
    //此处打印a变量,打印结果为请求所赋值的具体数据
    //因为await表达式的修饰,执行到console.log会有一个线程阻塞,
    //从而console.log会等待前面的异步执行操作执行完毕后再执行,
    //前面的异步请求执行完毕以后,变量a就被赋值成功了,从而能够
    //打印处请求到的数据。
    console.log(a)
}
getNews();

总结:上述两段代码都是在异步操作里取值(对a的赋值操作),
第一部分代码由于异步操作的原因,之后的同步操作先被执行了,
因而导致了没取到数据的情况。
而第二部分代码同为在异步操作里取值(对a的赋值操作),操作上是利用了
await会等待Promise执行完毕的特性,
(当resolve方法或reject方法执行完毕时,Promise的状态被确定,
则视Promise执行完毕)。
将resolve方法放在异步操作中取值传参,就可以做到异步操作的同步效果。
即:等待异步操作获取到数据之后再进行后续的其他相关操作的效果。

注意:使用此方法的话,取值必须在异步操作之中,不然依然会出现异步取值为空的问题
因为resolve方法是同步方法,若取值操作不在异步操作中,则异步操作就不会与await的
效果进行相应的绑定,则Promise的构造方法内部并没有起到线程阻塞的效果,
resolve方法会先被执行,从而导致取不到数据的情况。
(总结和注意的内容请认真看,上面都很重要,就不标红字体了)

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神奇的海螺丷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值