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 相关文章推荐
[原创]网络复制内容时常用的正则+editplus
Nov 30 Javascript
JS提交并解析后台返回的XML的代码
Nov 03 Javascript
表单元素事件 (Form Element Events)
Jul 17 Javascript
简单漂亮的js弹窗可自由拖拽且兼容大部分浏览器
Oct 22 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
Mar 18 Javascript
js简单实现图片延迟加载的方法
Jul 19 Javascript
PHP自动加载autoload和命名空间的应用小结
Dec 01 Javascript
完美解决axios在ie下的兼容性问题
Mar 05 Javascript
微信小程序转化为uni-app项目的方法示例
May 22 Javascript
Vue按时间段查询数据组件使用详解
Aug 21 Javascript
Openlayers实现点闪烁扩散效果
Sep 24 Javascript
js实现随机圆与矩形功能
Oct 29 Javascript
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
PHP编程基本语法快速入门手册
2016/01/07 PHP
PHP正则表达式匹配替换与分割功能实例浅析
2017/02/04 PHP
JavaScript中两个感叹号的作用说明
2011/12/28 Javascript
jquery表单验证使用插件formValidator
2012/11/10 Javascript
node.js中的fs.readFileSync方法使用说明
2014/12/15 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
2015/07/18 Javascript
Jquery数字上下滚动动态切换插件
2015/08/08 Javascript
avalon js实现仿google plus图片多张拖动排序附源码下载
2015/09/24 Javascript
详解JavaScript的Date对象(制作简易钟表)
2020/04/07 Javascript
高效Web开发的10个jQuery代码片段
2016/07/22 Javascript
JS如何设置cookie有效期为当天24点并弹出欢迎登陆界面
2016/08/04 Javascript
Javascript之深入浅出prototype
2017/02/06 Javascript
vue2.0的虚拟DOM渲染思路分析
2018/08/09 Javascript
微信小程序swiper使用网络图片不显示问题解决
2019/12/13 Javascript
详解Nuxt内导航栏的两种实现方式
2020/04/16 Javascript
Vue的v-model的几种修饰符.lazy,.number和.trim的用法说明
2020/08/05 Javascript
使用C语言扩展Python程序的简单入门指引
2015/04/14 Python
python中字典(Dictionary)用法实例详解
2015/05/30 Python
python中WSGI是什么,Python应用WSGI详解
2017/11/24 Python
对python字典元素的添加与修改方法详解
2018/07/06 Python
python 在指定范围内随机生成不重复的n个数实例
2019/01/28 Python
Python3实现的回文数判断及罗马数字转整数算法示例
2019/03/27 Python
Python3 文章标题关键字提取的例子
2019/08/26 Python
face++与python实现人脸识别签到(考勤)功能
2019/08/28 Python
Python3爬虫里关于Splash负载均衡配置详解
2020/07/10 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
2021/01/21 Python
CSS3实现精美横向滚动菜单按钮
2017/04/14 HTML / CSS
html5使用canvas画三角形
2014/12/15 HTML / CSS
管理科学大学生求职信
2013/11/13 职场文书
行政人员工作职责
2013/12/05 职场文书
2014年惩防体系建设工作总结
2014/12/01 职场文书
工程资料员岗位职责
2015/04/13 职场文书
自考生自我评价
2019/06/21 职场文书
Vue提供的三种调试方式你知道吗
2022/01/18 Vue.js
vue中div禁止点击事件的实现
2022/04/02 Vue.js
Pytorch中expand()的使用(扩展某个维度)
2022/07/15 Python