问题描述:以下这段代码的执行结果
    async function async1() {
console.log('async1 start');
await async2();
console.log('asnyc1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('setTimeOut');
}, 0);
async1();
new Promise(function (reslove) {
console.log('promise1');
reslove();
}).then(function () {
console.log('promise2');
})
console.log('script end');

解决问题:
要了解代码的执行顺序 必须先了解 JS的运行机制
  •  Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。
  • JS调用栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。
  •  Javascript单线程任务被分为同步任务异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。

JavaScript中,任务被分为两种,一种宏任务(MacroTask),一种叫微任务(MicroTask)。

MacroTask(宏任务)

  • script全部代码、setTimeoutsetInterval

MicroTask(微任务)

  • Promise、await
执行栈在执行完同步任务后,查看执行栈是否为空,如果执行栈为空,就会去检查微任务队列是否为空,如果为空的话,就执行宏任务,否则就一次性执行完所有微任务。
每次单个宏任务执行完毕后,检查微任务队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务后,设置微任务队列为null,然后再执行宏任务,如此循环。
 
 
运行之前我们需要知道以下几点
  • setTimeout属于宏任务
  • Promise本身是同步的立即执行函数,Promise.then属于微任务
  • async方法执行时,遇到await会立即执行表达式,表达式之后的代码放到微任务执行

下面我们就来运行代码

第一次执行:执行同步代码

Tasks(宏任务):run script、 setTimeout callback
Microtasks(微任务):await、Promise then
JS stack(执行栈): script
Log: script start、async1 start、async2、promise1、script end

第二次执行:执行宏任务后,检测到微任务队列中不为空、一次性执行完所有微任务

Tasks(宏任务):run script、 setTimeout callback
Microtasks(微任务):null
JS stack(执行栈): await、Promise then
Log: script start、async1 start、async2、promise1、script end、promise2、async1 end

第三次执行:当微任务队列中为空时,执行宏任务,执行setTimeout callback,打印日志。

Tasks(宏任务):null

Microtasks(微任务):null

JS stack(执行栈):setTimeout callback
Log: script start、async1 start、async2、promise1、script end、promise2、async1 end、setTimeout

关于73以下版本和73版本的区别

  • 在老版本版本以下,先执行promise2,再执行async1 end
  • 在73及以上版本,先执行async1 end再执行promise2
  • 具体资料可以查询  https://v8.js.cn/blog/fast-async/

 于是我们就得到了这段代码的执行结果(70版本)

(73及以上版本执行结果为)

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
 

最新文章

  1. eafier 簡單易用 HTML、CSS 網頁編輯器(可自動插入 Tag 標籤)
  2. javascript小技巧:同步服务器时间、同步倒计时
  3. iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver
  4. 1.1 MySQL 逻辑架构
  5. Lua与C++交互初探之Lua调用C++
  6. UML 小结(1)- 整体阐述
  7. oracle 字符集转换:AL32UTF8->ZHS16GBK
  8. 解决Robotium测试用例crash问题
  9. MFC下的日历表
  10. Thinkpad W540通过扩展坞连接显示器后蓝屏原因
  11. 【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)
  12. AVL树之 Java的实现
  13. MyBatis-plus二级缓存使用
  14. 新手vue构建单页面应用实例
  15. ReactiveX 学习笔记(25)使用 RxJS + Vue.js 调用 REST API
  16. app 性能
  17. SimpleDateFormat是线程不安全的,切忌切忌!
  18. select默认选择后台转过来的option选项
  19. ARMCC和GCC编译ARM代码的软浮点和硬浮点问题【转】
  20. 关于redis连接池

热门文章

  1. jQuery_完成表格的隔行换色
  2. (47)LINUX应用编程和网络编程之二Linux文件属性
  3. ELK日志平台搭建
  4. 4、kubernetes资源清单快速入门190625
  5. 在linux下搭建go环境
  6. Python学习之==>json处理
  7. .NetCore2.0项目之ABP+Vue(IView框架)单页应用之路,启动
  8. 操作系统(1)——X86-32硬件介绍、实验环境相关配置、uCore部分技巧介绍
  9. (转载)gcc编译选项总结
  10. 在线cron表达式生成工具