理解promise、async 和await之间的执行关系
先看下面的例子
console.log('script start');
async function async1(){console.log('async1 start');await async2();console.log('async1 end');
}
async function async2(){console.log('async2 end');
}
async1();
setTimeout(function(){console.log('setTimeout');
},0)
new Promise(resolve=>{console.log('Promise');resolve();
}).then(function(){console.log('promise1');
})console.log('script end');
复制代码
执行结果如下:
script start
async1 start
async2 end
Promise
script end
promise1
async1 end
setTimeout
复制代码
注意:在新的浏览器中打印的结果不是这样,是下面的样子
为什么会不一样? 我们先简单说一下是v8团队借鉴了node8中的一个Bug,为了提升性能,在引擎底层将三次tick减少到了2次。但是这样做违反了规范,不过规范也是人制定的,是可以在一定情况下,修改的。传送门,想了解的可以看这里
我们还是按照规范理解上面的打印结果
- 1.首先打印出script start (这个就不讲了)
- 2.执行到async1()的时候,首先会打印出async1 start,因为async表达式定义的函数也是立即执行的
- 3.然后执行到await async2(),发现saync2也是个async定义的函数,所以直接执行 async2 end,同时async2返回一个Promise,重点:此时返回的Promise会被放入到回调队列中等待,await会让出线程(js是单线程的),接下来跳出async1函数,继续往下执行;
- 4.然后执行到setTimeout,setTimeout是宏任务,会等到执行栈(调用栈)清空之后,微任务全部执行完毕之后,才会去执行,所以setTimeout会被挂起,最后执行
- 5.然后到了new Promise,new Promise是立即执行的,所以会立即打印出Promise;(Promise是一个立即执行的函数,但是它的成功(resolve())或失败(reject())回调函数确实一个异步执行的回调。) 然后执行resolve()的时候,resolve()这个任务会被放入回调队列中,等到调用栈有空闲的时候,事件循环(Event Loop)再来取走它, 这时候会跳出Promise,继续往下走
- 6.输出script end;
- 7.同步任务已经全部执行完毕,执行栈现在已经空闲出来,那么事件循环就会去回调队列中取任务继续放到执行栈中执行;
- 8.这时候取的第一个任务就是async2放进去的Promise,执行Promise的时候遇到了resolve函数,resolve又回被放入到任务队列中继续等待,然后再次跳出async1 继续下一个任务
- 9.接下来取走的就是new Promise放进去的resolve回调,这个被调用栈执行,并输出promise1,然后继续取下一个任务
- 10.这次终于取到了那么Promise的resolve回调,因为async2并没有return内容,所以这个resolve的参数是undefined,此时await定义的Promise已经执行完毕并且返回了结果,所以可以继续往下执行async1函数后面的任务了,于是输出async1 end
- 11.上面的微任务执行完毕之后,开始执行宏任务中的异步setTimeout
总结:Event Loop 执行顺序如下:
- 1 首先执行同步任务,这属于宏任务
- 2.当执行完所有同步任务代码之后,执行栈为空,查询是否有异步代码需要执行
- 3.执行所有微任务
- 4.当执行完所有微任务后,如果有必要会渲染页面
- 5.然后开始下一轮的Event Loop,执行宏任务中的异步代码,也就是setTimeout中的回调函数
宏任务:
- 1.script
- 2.setTimeout
- 3.setInterval
- 4.setImmediate
- 5.I/O
- 6.UI rendering
微任务:
- 1.process.nextTick(node 独有)
- 2.promise
- 3.MutationObserver
转载于:https://juejin.im/post/5cd387a86fb9a0323a01cd86
理解promise、async 和await之间的执行关系相关推荐
- C++ 有参构造 无参构造 拷贝构造 以及参数化列表 成员对象之间的执行关系
#include <iostream> #include <string> using namespace std; class Phone { public:string m ...
- async And await异步编程活用基础
async And await异步编程活用基础 原文:async And await异步编程活用基础 好久没写博客了,时隔5个月,奉上一篇精心准备的文章,希望大家能有所收获,对async 和 awai ...
- 【转】探索c#之Async、Await剖析
阅读目录: 基本介绍 基本原理剖析 内部实现剖析 重点注意的地方 总结 基本介绍 Async.Await是net4.x新增的异步编程方式,其目的是为了简化异步程序编写,和之前APM方式简单对比如下. ...
- 掌握JavaScript中的迭代器和生成器,顺便了解一下async、await的原理
掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 目录 掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 前言 1.迭代器(It ...
- Android 主线程子线程执行关系
Android 切换线程的方式[我常用的] 1. Handler.post[切换至主线程] 2. new Thread().start()[切换至子线程] 3. 线程池 ThreadP ...
- javascript之异步操作理解---回调函数,async,await以及promise对象
javascript之异步操作理解---回调函数,async,await以及promise对象 概述 概述 写在前面:虽然平时做项目,但是发现自己写的代码还是很烂.最近接触了一个对性能要求比较高的项目 ...
- Promise async/await的理解和用法
Promise && async/await的理解和用法 为什么需要promise(承诺)这个东西 在之前我们处理异步函数都是用回调这个方法,回调嵌套的时候会发现 阅读性 和 调试 的 ...
- rust异步编程--理解并发/多线程/回调/异步/future/promise/async/await/tokio
1. 异步编程简介 通常我们将消息通信分成同步和异步两种: 同步就是消息的发送方要等待消息返回才能继续处理其它事情 异步就是消息的发送方不需要等待消息返回就可以处理其它事情 很显然异步允许我们同时做更 ...
- 详解promise、async和await的执行顺序
说明: 本文摘自 详解 promise.async和await的执行顺序. 1.题目和答案 一道题题目:下面这段promise.async和await代码,请问控制台打印的顺序? async func ...
最新文章
- 基于JavaWeb实现ATM机系统
- 华为服务器故障灯不开机_总有故障灯亮却不知道是怎么回事?详解这些你不认识的故障灯...
- KA,连接池居然这么简单?
- 成都内推 | 腾讯游戏王者荣耀算法团队招聘算法实习生
- Uboot分析(三)
- virtualbox php mac,详解mac下通过docker搭建LEMP环境
- Github项目推荐|可视化 GAN 的训练过程
- php统计在一个页面停留时间,php记录页面停留时间的代码
- java 球弹跳的高度_关于皮球弹跳高度的几个问题
- android系统的刷机步骤,安卓系统刷机教程的操作
- 【数据结构与算法】之深入解析“香槟塔”的求解思路与算法示例
- 从gRPC的重试策略说起
- 迅搜 php,安装、升级 - 权威指南 - 迅搜(xunsearch) - 开源免费中文全文搜索引擎
- Python3中print的高级用法——print中执行命令和函数:print(*meta)
- java 风的角度转风向
- 大数据平台,Hadoop集群架构,概述及原理
- dns dnsmasq容器化部署
- k8s 通过helm发布应用
- 企业权限管理用什么软件比较好?
- 矿大计算机学院周裕浩,计算机学院学子在第45届ACM-ICPC亚洲区决赛获佳绩