Js中async/await的执行顺序详解


Posted in Javascript onSeptember 22, 2017

前言

虽然大家知道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的任务队列执行顺序的问题,就下次再述。如果大家对有什么意见或建议可以指出。本篇是我第一次发布文章,希望大家不吝赐教。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jQuery EasyUI NumberBox(数字框)的用法
Jul 08 Javascript
suggestion开发小结以及对键盘事件的总结(针对中文输入法状态)
Dec 20 Javascript
原生javascript和jquery判断浏览器版本等信息
Jul 04 Javascript
javascript中加号(+)操作符的一些神奇作用
Jun 06 Javascript
javascript格式化指定日期对象的方法
Apr 21 Javascript
基于js实现微信发送好友如何分享到朋友圈、微博
Nov 30 Javascript
js中scrollTop()方法和scroll()方法用法示例
Oct 03 Javascript
jQuery实现的简单拖动层示例
Feb 22 Javascript
Angular2的管道Pipe的使用方法
Nov 07 Javascript
vue-cli扩展多模块打包的示例代码
Apr 09 Javascript
node结合swig渲染摸板的方法
Apr 11 Javascript
jQuery实现点击图标div循环放大缩小功能
Sep 30 jQuery
Node.js自定义实现文件路由功能
Sep 22 #Javascript
详解bootstrap用dropdown-menu实现上下文菜单
Sep 22 #Javascript
javascript计算渐变颜色的实例
Sep 22 #Javascript
利用Node.js了解与测量HTTP所花费的时间详解
Sep 22 #Javascript
原生JS实现日历组件的示例代码
Sep 22 #Javascript
BootstrapTable加载按钮功能实例代码详解
Sep 22 #Javascript
Bootstrap Table 删除和批量删除
Sep 22 #Javascript
You might like
一条久听不愿放下的DIY森海MX500,三言两语话神奇
2021/03/02 无线电
Home Coffee Roasting
2021/03/03 咖啡文化
php查找任何页面上的所有链接的方法
2013/12/03 PHP
PHP中的use关键字及文件的加载详解
2016/11/28 PHP
php把文件设置为插件的技巧方法
2020/02/03 PHP
Event altKey,ctrlKey,shiftKey属性解析
2013/12/18 Javascript
jquery 取子节点及当前节点属性值
2014/07/25 Javascript
jQuery控制网页打印指定区域的方法
2015/04/07 Javascript
jquery中trigger()无法触发hover事件的解决方法
2015/05/07 Javascript
jQuery实现标签页效果实战(4)
2017/02/08 Javascript
js模拟百度模糊搜索的实例
2017/08/04 Javascript
js es6系列教程 - 新的类语法实战选项卡(详解)
2017/09/02 Javascript
使用JavaScript实现node.js中的path.join方法
2018/08/12 Javascript
node中的session的具体使用
2018/09/14 Javascript
解决三元运算符 报错“SyntaxError: can''t assign to conditional expression”
2020/02/12 Javascript
JavaScript实现简单日历效果
2020/09/11 Javascript
全面解析Vue中的$nextTick
2020/12/24 Vue.js
Python re模块介绍
2014/11/30 Python
Python栈类实例分析
2015/06/15 Python
pytorch permute维度转换方法
2018/12/14 Python
Python之NumPy(axis=0 与axis=1)区分详解
2019/05/27 Python
用Python爬取QQ音乐评论并制成词云图的实例
2019/08/24 Python
Python基于QQ邮箱实现SSL发送
2020/04/26 Python
python 解决函数返回return的问题
2020/12/05 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
python上下文管理的使用场景实例讲解
2021/03/03 Python
阿波罗盒子:Apollo Box
2017/08/14 全球购物
英国经济型酒店品牌:Travelodge
2019/12/17 全球购物
西班牙鞋子和箱包在线销售网站:zapatos.es
2020/02/17 全球购物
给定一个时间点,希望得到其他时间点
2013/11/07 面试题
优秀毕业生推荐信范文
2014/03/07 职场文书
上课玩手机的检讨书
2014/10/01 职场文书
2014房屋登记授权委托书
2014/10/13 职场文书
2014年大班保育员工作总结
2014/12/02 职场文书
小学生心理健康活动总结
2015/05/08 职场文书
nginx配置文件使用环境变量的操作方法
2021/06/02 Servers