资讯专栏INFORMATION COLUMN

async/await 执行顺序详解

derek_334892 / 2092人阅读

摘要:怎么处理返回值输出结果从结果中可以看到函数返回的是一个对象,如果在函数中一个直接量,会把这个直接量通过封装成对象。如果函数没有返回值结果结果返回。

随着async/await正式纳入ES7标准,越来越多的人开始研究据说是异步编程终级解决方案的 async/await。但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await(如果对async/await不熟悉可以先看下这篇文章)后拓展了一下,我理了一下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的执行顺序,在研究过程中还发现了js的任务队列执行顺序的问题,就下次再述。如果大家对有什么意见或建议可以指出。本篇是我第一次发布文章,希望大家不吝赐教。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88573.html

相关文章

  • 搞懂一道async await, promise, setTimeout执行顺序的前端面试题

    摘要:不再废话,下面见题执行执行输出结果执行执行这道题最难理解的地方和的执行顺序,前面的结果一般没有异议,如果不明白,百度一下变可以理解。 先指明这道题是面试题的改版,原题可以看:promise、async和await之执行顺序的那点事这道题也不是我改的,出处见:async/await 执行顺序详解 这两篇文章写的非常好,我仔细琢磨了一下,感觉受益匪浅,决定记录一下自己的理解。不再废话,下面...

    Jrain 评论0 收藏0
  • 8张图帮你一步步看清 async/await 和 promise 的执行顺序

    摘要:第部分画图一步步看清宏任务微任务的执行过程我们以开篇的经典面试题为例,分析这个例子中的宏任务和微任务。注意这里只是把推入微任务队列,并没有执行。执行结束,才能继续执行后面的代码如图此时当前宏任务都执行完了,要处理微任务队列里的代码。 8张图让你一步步看清 async/await 和 promise 的执行顺序 为什么写这篇文章? 测试一下自己有没有必要看 需要具备的前置基础知识 主...

    weizx 评论0 收藏0
  • 现代JS中的流程控制:详解Callbacks 、Promises 、Async/Await

    摘要:控制台将显示回调地狱通常,回调只能由一个异步函数调用。更多资源使更友好规范使用异步函数简化异步编码旅程异步编程是一项在中无法避免的挑战。 JavaScript经常声称是_异步_。那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每...

    shadowbook 评论0 收藏0
  • 现代JS中的流程控制:详解Callbacks 、Promises 、Async/Await

    摘要:控制台将显示回调地狱通常,回调只能由一个异步函数调用。更多资源使更友好规范使用异步函数简化异步编码旅程异步编程是一项在中无法避免的挑战。 JavaScript经常声称是_异步_。那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每...

    oujie 评论0 收藏0
  • 现代JS中的流程控制:详解Callbacks 、Promises 、Async/Await

    摘要:控制台将显示回调地狱通常,回调只能由一个异步函数调用。更多资源使更友好规范使用异步函数简化异步编码旅程异步编程是一项在中无法避免的挑战。 JavaScript经常声称是_异步_。那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每...

    anquan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<