林大妈的JavaScript进阶知识(二):JS异步行为
JavaScript 是单线程执行的
JavaScript运行在浏览器中。浏览器是多线程的,但只分配了其中一条给JavaScript,作为它的主线程。对于编码者来说,JavaScript是单线程的。因此JavaScript中存在以下几种异步行为:
- 事件绑定(addEventListener)
- 定时器(setTimeout、setInterval)
- AJAX(axios)、fetch
- 所有跟Promise的resolve、reject相关的行为(generator、async/await)
JavaScript 异步执行情况
其中WEB API会执行类似setTimeout的倒数或发送AJAX请求这样的操作,而得到的返回值则会加入Event Queue中等待主栈为空时压栈执行。
练习题目
// 以下的程序将会按照如何的顺序执行?
async function async1 () {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2 () {
console.log('async2')
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout')
}, 0)
async1()
new Promise((resolve) => {
console.log('promise1')
resolve()
}).then(() => {
console.log('promise2')
})
console.log('script end')
代码的基本分析:
- 第二到第十行,两个异步函数声明,不会输出东西
- 第十二到第二十七行,中间全部是函数执行的代码,可以把它看作主函数
- 第十二行是简单的输出语句
- 十四到十六行是一个setTimeout,通过前面的学习我们知道它会加入宏任务队列
- 第十八行是async1函数的执行,其中有一个async函数的嵌套,它把async2嵌套在了1中的await语句里
- 接着20行是一个Promise对象的声明,声明Promise对象需要传一个名为executor的参数,这个executor是会在声明的时候直接执行的,紧接着23行是一个then回调,通过前面的学习我们知道它会加入微任务队列
- 最后是一个普通的输出语句
因此这题的难点就是在async语句的嵌套中。首先,根据前面的分析,因为前面都是函数声明,不会输出内容,代码会先输出script start,然后setTimeout加入宏任务队列。接下来进入异步函数async1,我们知道,异步函数本质上是generator的语法糖,因此异步函数会一直同步地执行到await语句执行完毕,并且把下面的代码放到微任务队列中,因此代码执行到此还会依次输出async1 start和async2。紧接着创建Promise对象时executor被执行,输出promise1,并把then放入微任务中,最后输出script end。理论上说,到此JS主线程已经执行完毕,也就是主栈中是空的,接下来就要分别看微任务和宏任务队列了。看微任务队列中现在有两个Task,按刚才所说的顺序是先是async1 end,再是promise2,但此处V8引擎版本不同执行情况不同,有的版本是按照队列顺序执行,有的是先执行Promise再执行await后的语句(但新版本的V8引擎是属于先执行Promise这种情况的,因此会输出promise2和async1 end)。这种现象可能是由于底层实现中await转化为promise语句是放在加入队列前还是加入队列后执行的关系,但无论如何它们两个微任务都必会在宏任务前执行,因此最后会输出宏任务的setTimeout。
总结
异步编程需要比较细地掌握它们三个微任务:
- async/await
- Promise
- generator
搞清楚基本的执行顺序即可,也不必要苛求每处都完全正确。
林大妈的JavaScript进阶知识(二):JS异步行为的更多相关文章
- 林大妈的JavaScript进阶知识(一):对象与内存
JavaScript中的基本数据类型 在JS中,有6种基本数据类型: string number boolean null undefined Symbol(ES6) 除去这六种基本数据类型以外,其他 ...
- 林大妈的JavaScript进阶知识(三):HTML5 History API
HTML5中新增了History API,它用于管理浏览器路由跳转的一个url栈.History是window对象的一部分,它也是一个对象,因此称它是BOM(类似DOM,Browser Object ...
- 林大妈的JavaScript基础知识(三):JavaScript编程(2)函数
JavaScript是一门函数式的面向对象编程语言.了解函数将会是了解对象创建和操作.原型及原型方法.模块化编程等的重要基础.函数包含一组语句,它的主要功能是代码复用.隐藏信息和组合调用.我们编程就是 ...
- 林大妈的JavaScript基础知识(三):JavaScript编程(3)原型
在一般的编程语言中,我们使用继承来复用代码,做成良好的数据结构.而在JavaScript中,我们使用原型来实现以上的需求.由于JavaScript专注于对象而摒弃了类,我们要明白原型和继承的确是有差异 ...
- 林大妈的JavaScript基础知识(二):编写JavaScript代码前的一些简单工作
在介绍JavaScript语法前,我们需要知道,学习语法必须要多利用手敲代码来巩固记忆.因此,由于JavaScript的特性,它不能像C++和Java一样独立地编译及运行,我们需要在调试运行JavaS ...
- 林大妈的JavaScript基础知识(三):JavaScript编程(4)数组
数组,是一段线性分配的,具有非常高性能的数据结构.简单地说,数组以连续的空间存储,通过整数地计算偏移量访问其中的元素,将读取修改的时间复杂度降低至O(1),我们称之为猝发式存取.是不是非常期待?没错, ...
- 林大妈的JavaScript基础知识(一):JavaScript简史
前言:做一名Web设计师是一件令人兴奋的事.在Web技术中,JavaScript是一个经历从被人误解到万众瞩目的巨大转变,在历史的冲击中被留存下来的个体.因为JavaScript的引导,Web开发也从 ...
- 林大妈的JavaScript基础知识(三):JavaScript编程(1)对象
1. 对象的简单介绍与一些注意事项 JavaScript中具有几个简单数据类型:数字.字符串.布尔值.null值以及undefined值.除此之外其余所有值(包括数组.函数,甚至正则表达式)都是对象. ...
- JavaScript进阶(二)
什么是事件 JavaScript 创建动态页面.事件是可以被 JavaScript 侦测到的行为. 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件. 比如说,当用户单击 ...
随机推荐
- Javascript小白经典题型(一)
1. 输出是什么? function sayHi() { console.log(name) console.log(age) var name = 'Lydia' let age = 21 } sa ...
- iOS - 点击背景视图收起系统键盘
我们在 IOS 开发中经常会需要在输入框输入数据后,需要收起系统键盘,比如由于手机屏幕不是很大,可能由于输入信息后,系统键盘就会遮挡住下一步的按钮,而系统键盘有没有收起键,所以我们可以实现点击背景视图 ...
- 记录这两年是如何一步一步转型到.net core+k8s
2017年12月份,我离开北京,回到了武汉,开始在现在这家公司担任架构师工作.经过2年的时间,逐步完成以.net core+k8s为核心的技术架构.文末有彩蛋. 以下整理这两年的主要时间节点: 201 ...
- bootstrapValidator JS修改内容无法验证
需求: form表单输入中有坐标,坐标可以输入也可以从地图中获取,验证插件使用的是 bootstrapValidator 问题: 当输入错误的值时会触发验证,有错误提示.当在地图上选择坐标,通过js修 ...
- spring-boot内嵌三大容器https设置
spring-boot内嵌三大容器https设置 spring-boot默认的内嵌容器为tomcat,除了tomcat之前还可以设置jetty和undertow. 1.设置https spring-b ...
- Django3.0.2学习踩坑记
配置文件settings.py相关: 新增app INSTALLED_APPS = [ 'polls.apps.PollsConfig', # 这个是新增的APP 'django.contrib.ad ...
- 【Tool】---SVN的超级简单并具体得使用介绍
又一次被打脸,笔者表示再也不相信自己的记性了.简单的SVN隔了一段时间后,由于项目的需要要重新简历代码库,竟然一下子又忘了.天那,这就好比战士上了战场发现没带枪,这能行吗?因此,趁着今天又简短的复习了 ...
- woj - 将一个问题转换为背包问题
Problem 1538 - B - Stones II Time Limit: 1000MS Memory Limit: 65536KB Total Submit: 428 Accepte ...
- border 边框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- java 自增/减运算符
注意:python中没有 一.自增运算符 1.单独使用时,目的获取变量的值,前++和后++没有区别,使用后值都会递增一. 2.混合使用时,才有区别.前++,先加后用.后++,先用后加 二.自减运算符 ...