zoukankan      html  css  js  c++  java
  • JS中的async/await的执行顺序详解

    虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await(如果对async/await不熟悉可以先看下http://es6.ruanyifeng.com/#docs/async)后拓展了一下,我理了一下await之后js的执行顺序,希望可以给别人解疑答惑,先简单介绍一下async/await。

    • async/await 是一种编写异步代码的新方法。之前异步代码的方案是回调和 promise。
    • async/await 是建立在 promise 的基础上。
    • async/await 像 promise 一样,也是非阻塞的。
    • async/await 让异步代码看起来、表现起来更像同步代码。这正是其威力所在。

    async怎么处理返回值

    async function testAsync() {
     return "hello async";
    }
    let result = testAsync();
    console.log(result)
    //输出结果:Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello async"

    从结果中可以看到async函数返回的是一个promise对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。

    如果asyn函数没有返回值

    async function testAsync1() {
     console.log("hello async");
    }
    let result1 = testAsync1();
    console.log(result1);
    //结果:hello async
        Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
     

    结果返回Promise.resolve(undefined)

    await做了什么处理

    从字面意思上看await就是等待,await 等待的是一个表达式,这个表达式的返回值可以是一个promise对象也可以是其他值。

    很多人以为await会一直等待之后的表达式执行完之后才会继续执行后面的代码,实际上await是一个让出线程的标志。await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈(后面会详述)的代码。等本轮事件循环执行完了之后又会跳回到async函数中等待await

    后面表达式的返回值,如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise放入promise队列(Promise的Job Queue)

    async/await 执行顺序

    先看一个例子

    function testSometing() {
     console.log("执行testSometing");
     return "testSometing";
    }
     
    async function testAsync() {
     console.log("执行testAsync");
     return Promise.resolve("hello async");
    }
     
    async function test() {
     console.log("test start...");
     const v1 = await testSometing();//关键点1
     console.log(v1);
     const v2 = await testAsync();
     console.log(v2);
     console.log(v1, v2);
    }
     
    test();
     
    var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//关键点2
    promise.then((val)=> console.log(val));
     
    console.log("test end...")

    输出结果:

    test start...
    执行testSometing
    promise start..
    test end...
    testSometing
    执行testAsync
    promise
    hello async
    testSometing hello async

    当test函数执行到

    const v1 = await testSometing();

    的时候,会先执行testSometing这个函数打印出“执行testSometing”的字符串,然后因为await会让出线程就会区执行后面的

    var promise = new Promise((resolve)=> { console.log("promise
    start.."); resolve("promise");});//关键点2

    然后打印出“promise start..”接下来会把返回的这promise放入promise队列(Promise的Job Queue),继续执行打印“test end...”,等本轮事件循环执行结束后,又会跳回到async函数中(test函数),等待之前await 后面表达式的返回值,因为testSometing 不是async函数,所以返回的是一个字符串“testSometing”,test函数继续执行,执行到

    const v2 = await testAsync();

    和之前一样又会跳出test函数,执行后续代码,此时事件循环就到了promise的队列,执行promise.then((val)=> console.log(val));then后面的语句,之后和前面一样又跳回到test函数继续执行。

    这个就是在async/await 函数之后js的执行顺序,我们再看一个列子把testSometing函数前面加上async

    async function testSometing() {
     console.log("执行testSometing");
     return "testSometing";
    }
     
    async function testAsync() {
     console.log("执行testAsync");
     return Promise.resolve("hello async");
    }
     
    async function test() {
     console.log("test start...");
     const v1 = await testSometing();
     console.log(v1);
     const v2 = await testAsync();
     console.log(v2);
     console.log(v1, v2);
    }
     
    test();
     
    var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//3
    promise.then((val)=> console.log(val));
     
    console.log("test end...")

    输出结果:

    test start...
    执行testSometing
    promise start..
    test end...
    promise
    testSometing
    执行testAsync
    hello async
    testSometing hello async
     

    和上一个例子比较发现promise.then((val)=> console.log(val));先与console.log(v1);执行了,原因是因为现在testSometing函数加了async,返回的是一个Promise对象要要等它resolve,所以将当前Promise推入队列,所以会继续跳出test函数执行后续代码。之后就开始执行promise的任务队列了,所/以先执行了promise.then((val)=> console.log(val));因为这个Promise对象先推入队列;

    总结

    写到这里大家应该已经清楚了使用async/await进行异步操作时js的执行顺序。如果大家对有什么意见或建议可以指出,希望大家不吝赐教。

  • 相关阅读:
    NGUI Sprite 和 Label 改变Layer 或父物体后 未更新深度问题
    unity销毁层级物体及 NGUI 深度理解总结
    unity 2d 和 NGUI layer
    关于NGUI与原生2D混用相互遮盖的问题心得
    CentOS7为firewalld添加开放端口及相关操作
    Python 操作redis有序集合(sorted set)
    win10下安装redis 服务
    python2/3中 将base64数据写成图片,并将图片数据转为16进制数据的方法、bytes/string的区别
    解决最小化安装Centos7后无法上网的问题,以及安装成功后的基本配置
    在mysql中使用group by和order by取每个分组中日期最大一行数据,亲测有效
  • 原文地址:https://www.cnblogs.com/liutianzeng/p/10975343.html
Copyright © 2011-2022 走看看