async/await 执行顺序详解
随着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中的async/await的执行顺序详解
虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await(如果对async/await不熟悉 ...
- Unity 继承MonoBehaviour脚本 执行顺序 详解
先看结果 Awake ->OnEnable-> Start ->-> FixedUpdate-> Update -> LateUpdate ->OnGUI ...
- 错误的理解引起的bug async await 执行顺序
今天有幸好碰到一个bug,让我知道了之前我对await async 的理解有点偏差. 错误的理解 之前我一直以为 await 后面的表达式,如果是直接返回一个具体的值就不会等待,而是继续执行asyn ...
- setTimeout,promise,promise.then, async,await执行顺序问题
今天下午看了好多关于这些执行顺序的问题 经过自己的实践 终于理解了 记录一下就拿网上出现频繁的代码来说: async function async1() { console.log('async1 ...
- async/await使用深入详解
async和await作为异步模型代码编写的语法糖已经提供了一段时间不过一直没怎么用,由于最近需要在BeetleX webapi中集成对Task方法的支持,所以对async和await有了深入的了解和 ...
- Promise嵌套问题/async await执行顺序
/* 原则: 执行完当前promise, 会把紧挨着的then放入microtask队尾, 链后面的第二个then暂不处理分析, */ 一. new Promise((resolve, reject) ...
- javascript运行机制之执行顺序详解(转)
转自http://www.admin10000.com/document/3385.html JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言, ...
- 【Node.js】Event Loop执行顺序详解
本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...
- javascript 执行顺序详解
JavaScript是一种描述 型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行.如果你不能理解javaScript 语言的运行机制,或者简 ...
随机推荐
- Linux主机SSH免密设置解析
为了保证一台Linux主机的安全,所以我们每个主机登录的时候一般我们都设置账号密码登录.但是很多时候为了操作方便,我们都通过设置SSH免密码登录.那么该如何设置?是不是免密码登录就不安全了呢? 一.被 ...
- Spring框架(三) JDBCTemplate,声明式事务,自动装载(注解)
JDBCTemplate 按照标准正常项目的结构 结构图: model层 dao层 实现 dao:(DateBase Access Object) 数据访问对象,dao层只用来访问数据库和模型层 s ...
- iOS 模拟器安装应用
iOS模拟器是苹果Xcode IDE的一部分,主要用来为Mac,iPhone和iPad创建应用程序,为了给iOS模拟器打包应用程序,利用–package 在命令行上执行ADT并使用–target来指定 ...
- MySQL创建用户与授权方法
最近在弄个mysql兼职项目,记录一下: 一, 创建用户: 命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明:username ...
- 开启tomcat的apr模式,并利用redis做tomcat7的session的共享。
更新系统组件 yum -y install readline* xmlto kernel-devel yum* screen vim* psmisc wget lrzsz pcre-devel lib ...
- rpm 命令详解
参考:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/10/08/2203153.html rpm是由红帽公司开发的软件包管理方式,使用r ...
- Nginx (一) 认识Nginx并进行安装
Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗斯访问量第二的R ...
- Golang 网络爬虫框架gocolly/colly 四
Golang 网络爬虫框架gocolly/colly 四 爬虫靠演技,表演得越像浏览器,抓取数据越容易,这是我多年爬虫经验的感悟.回顾下个人的爬虫经历,共分三个阶段:第一阶段,09年左右开始接触爬虫, ...
- maven jar包冲三种解决方式
初次启动应用,一直包如下错误,起初怀疑引入pandora 版本冲突. Exception in thread "main" java.lang.NoSuchMethodError: ...
- Python核心编程--浅拷贝与深拷贝
一.问题引出浅拷贝 首先看下面代码的执行情况: a = [1, 2, 3] print('a = %s' % a) # a = [1, 2, 3] b = a print('b = %s' % b) ...