前端async await使用方法

程序员提升,逃不过的一个话题就是代码的执行效率,后端如此,前端也是如此,所以async/await异步开发就是大家提升自己代码效率的一个重要知识点,Python如此,JS亦如此,那么我们今天基于JS聊聊async/await异步编程。

异步

还是,先聊聊基础的概念,异步,他的反义词是同步,追究根源,要聊到计算机原理当中的进程和执行队列,简单来说就是在常规情况下,我们执行一个功能,在当前功能执行的过程当中,如果遇到文件内容加载或者是等待响应,那么程序就会进入阻塞状态,不会立马给出响应,也不会继续执行新的工作,那么基于前端发送邮件来举例:

(1)请求发送邮件

(2)邮件发送中

(3)页面等待邮件发送完成

(4)用户等待页面响应

(5)用户烦了,开始刷新页面重试

(6)重复上面步骤2-3次,用户骂骂咧咧或者叽叽歪歪的走了

(7)差评

所以基于上面的描述,可以看到阻塞不但影响代码执行的效率,对于用户体验来说也是非常致命的,那么,就有了异步的概念,所谓的异步就是在发起执行之后,程序进入等待,不进入阻塞状态,而是继续执行下面的功能,知道等待结束返回结果,再次进行响应,显而易见,他可以很好的避免上面的问题。基于前端,我最初了解的异步是ajax,异步请求,局部刷新页面,当时感觉相当nice,但是逐渐发现ajax只是对请求进行了异步,对需要异步的函数并没有太好的解决方式,那么这种情况下就有了async和await

async

作为一个关键字放在函数的前面,表示这个函数是一个异步函数,那么这个函数的执行不会阻塞后面代码的执行,但是异步函数的调用和普通函数是一样的,但是返回结果不一样。

<script>
    async function say_hello() {
    
    
        return "hello world"
    }
​
    console.log(say_hello()); //Promise 对象
    console.log("hi man") //
</script>

可以看到say_hello被转换为异步函数之后,并没有直接返回结果,而是返回了一个Promise对象,通过调试模式,我们可以看到再promise上面由几个方法,根据单词的含义有点像生命周期。我们依次调用看看。

image.png

<script>
        async function say_hello(f) {
    
    
            if(f === 1){
    
    
                return "hello world";
            }else{
    
    
                throw new Error("这里要发生错误"); //引发错误
            }
        }
        say_hello().catch((args)=>{
    
    
            console.log("catch 被调用了");
            console.log(args);
            console.log("catch 被调用了");
        });say_hello().finally(()=>{
    
    
            console.log("finally 被调用了收尾");
        });say_hello().then((args)=>{
    
    
            console.log("then 被调用了");
            console.log(args);
            console.log("then 被调用了");
        });
​
        console.log(say_hello(1));
</script>

constructor后面详细聊,那么下面的三个函数很明显可以看出是再不同状态下执行的

方法 描述
catch 有参数,在异步函数当中发生错误的时候执行,参数接收的是错误的内容
then 有参数,在异步函数正常完成后执行,参数是异步函数返回的结果
finally 在错误函数执行完成后执行,如没有发生作为,先于then执行

更加深入的聊就是:Promise对象有一个状态,如果Promise 对象状态变为resolved,调用then方法指定的回调函数;如果异步函数抛出错误,状态就会变为rejected,调用catch方法指定的回调函数,处理这个错误。而finally就是用来在错误后收尾的函数,而且要注意到是:then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。

await

await即等待,用于等待一个Promise对象执行(有点协程的意思了啊)。它只能在异步函数 async function中使用,如果它等到的不是一个 promise 对象,那 await 表达式的运算结果就是它等到的东西。如果它等到的是一个 promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

<script>
    async function say_hai(){
    
    
        return "hi world"
    }async function say_hello() {
    
    
        await say_hai().then((args)=>{
    
    
            console.log("hi man")
        }); //这里await右侧是一个异步函数,所以会阻塞程序,到这个异步函数执行完成之后,再往下执行
        return "hello world"
    }say_hello().then((args)=>{
    
    
        console.log("then 被调用了");
        console.log(args);
        console.log("then 被调用了");
    });
​
    console.log(say_hello());
</script><script>
    function say_hai(){
    
    
        return "hi world"
    }async function say_hello() {
    
    
        const res = await say_hai(); //这里await右侧是一个常规函数,所以await只是拿到了函数返回的结果
        console.log(res);
        return "hello world"
    }say_hello().then((args)=>{
    
    
       console.log("then 被调用了");
       console.log(args);
       console.log("then 被调用了");
    });
​
    console.log(say_hello());
</script>

所以await通常用在异步函数当中阻塞执行另外的一个异步函数,如果结合生产消费者,一个异步函数生产,一个异步函数消费,在生产的内部使用await调用消费就会产生生产一个,调用一个,并且在生产和调用函数执行过程当中进行来回切换的效果,执行效果更加地同步。

但是注意:

await 关键字会阻塞其后的代码,直到promise完成,就像执行同步操作一样,所以不恰当的使用过多的await,每个await都会等待前一个完成, 那么就失去了使用异步函数的意义。

猜你喜欢

转载自blog.csdn.net/weixin_45506717/article/details/131834352