虽然大家知道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");});//
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中的async/await的执行顺序详解的更多相关文章

  1. js中的async await

    JavaScript 中的 async/await 是属于比较新的知识,在ES7中被提案在列,然而我们强大的babel粑粑已经对它进行列支持! 如果开发中使用了babel转码,那么就放心大胆的用吧. ...

  2. Unity 继承MonoBehaviour脚本 执行顺序 详解

    先看结果 Awake ->OnEnable-> Start ->-> FixedUpdate-> Update  -> LateUpdate ->OnGUI ...

  3. async/await 执行顺序详解

    随着async/await正式纳入ES7标准,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 ...

  4. setTimeout、Promise、Async/Await 的执行顺序

    问题描述:以下这段代码的执行结果 async function async1() { console.log('async1 start'); await async2(); console.log( ...

  5. 【Node.js】Event Loop执行顺序详解

    本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...

  6. 【C# TAP 异步编程】三、async\await的运作机理详解

    [原创] 本文只是个人笔记,很多错误,欢迎指出. 环境:vs2022  .net6.0 C#10 参考:https://blog.csdn.net/brook_shi/article/details/ ...

  7. js中的事件委托或是事件代理详解

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  8. javascript运行机制之执行顺序详解(转)

    转自http://www.admin10000.com/document/3385.html JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言, ...

  9. javascript 执行顺序详解

    JavaScript是一种描述 型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行.如果你不能理解javaScript 语言的运行机制,或者简 ...

随机推荐

  1. 树状数组的神操作QAQ

    卧槽 厉害了,我的树状数组 1.单点修改,单点查询 用差分数组维护 #include<cstdio> #include<iostream> using namespace st ...

  2. [USACO08JAN]跑步Running dp

    题目描述 The cows are trying to become better athletes, so Bessie is running on a track for exactly N (1 ...

  3. 检测工具lynis

    wget https://gitee.com/zzhlinux911218/software/raw/master/linux-inspect2.sh;bash linux-inspect2.sh检测 ...

  4. chapter05

    /** * Created by EX-CHENZECHAO001 on 2018-03-29. */class Chapter05 { } // 类// 类中的字段自动带有getter方法和sett ...

  5. SpringCloud+MyBatis+Redis整合—— 超详细实例(一)

    1.SpringCloud+MyBatis MyBatis 是一款优秀的轻量级半自动持久层框架,与之相对应的还有hibernate框架.①   话不多说,接下来搭建SpringCloud+MyBati ...

  6. matlab 文件打开设置

    平台 macOS MATLAB 版本 matlab 2017a 需要设置文件打开编码的情况 从windows平台迁移过来的.m文件的编码格式是GB2312的, 而macOS的MATLAB默认是UTF- ...

  7. [luogu 3369]普通平衡树(fhq_treap)

    题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多 ...

  8. java如何导入Excel文件

    Java使用POI导入Excel文件,操作起来比较简单,支持xlsx格式. 下载POI资源包 从官网https://poi.apache.org/下载POI,笔者选择的是版本是3.17,下载后文件名是 ...

  9. Teradata 认证系列 - 2. Teradata数据库总览

    Teradata (以下简称TD) 总览本课的学习目标 描述Teradata数据库产品的功能 知晓支持的操作系统 描述Teradata的并行架构 解释线性可扩展性 列出Teradata DBA永远不需 ...

  10. 从零开始的全栈工程师——js篇2.8

    DOM(document object model) DOM主要研究htmll中的节点(也就是标签) 对节点进行操作    可以改变标签  改变标签属性  改变css样式  添加事件 一.操作流程 1 ...