当前位置:网站首页>js运行机制
js运行机制
2022-07-21 05:05:00 【大莲芒】
JavaScript执行机制,重点有两点:
- JavaScript是一门单线程语言
- Event Loop(事件循环)是JavaScript的执行机制
JS为什么是单线程
最初设计JS是用来在浏览器验证表单操控DOM元素的是一门脚本语言,如果js是多线程的,那么两个线程同时对一个DOM元素进行了相互冲突的操作,那么浏览器的解析器是无法执行的。
js为什么需要异步
如果js中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。
对于用户而言,阻塞就以为着“卡死”,这样就导致了很差的用户体验。比如在进行ajax请求的时候如果没有返回数据后面的代码就没办法执行
JS的事件循环(eventloop)是怎么运作的
- 首先判断JS是同步还是异步,同步就进入主线程运行,异步就进入event table.
- 异步任务在event table中注册事件,当满足触发条件后,(触发条件可能是延时也可能是ajax回调),被推入event queue
- 同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程中。
如图所示:
那怎么知道主线程执行栈为空呢?js引擎存在monitoring process进程,会持续不断的检查 主线程执行栈是否为空,一旦为空,就会去event queue那里检查是否有等待被调用的函数
宏任务 包含整个script代码块,setTimeout, setIntval
微任务 Promise , process.nextTick
在划分宏任务、微任务的时候并没有提到async/ await的本质就是Promise
setTimeout(function() {
console.log('4')
})
new Promise(function(resolve) {
console.log('1') // 同步任务
resolve()
}).then(function() {
console.log('3')
})
console.log('2')
执行结果: 1-2-3-4
1. 这段代码作为宏任务,进入主线程。
2. 先遇到setTimeout,那么将其回调函数注册后分发到宏任务event queue.
3. 接下来遇到Promise, new Promise立即执行,then函数分发到微任务event queue
4. 遇到console.log(), 立即执行
5. 整体代码script作为第一个宏任务执行结束, 查看当前有没有可执行的微任务,执行then的回调。(第一轮事件循环结束了,我们开始第二轮循环)
6. 从宏任务的event queue开始,我们发现了宏任务event queue中setTimeout对应的回调函数,立即执行。
console.log('1')
setTimeout(function() {
console.log('2')
process.nextTick(function() {
console.log('3')
})
new Promise(function(resolve) {
console.log('4')
resolve()
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6')
})
new Promise(function(resolve) {
console.log('7')
resolve()
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9')
process.nextTick(function() {
console.log('10')
})
new Promise(function(resolve) {
console.log('11')
resolve()
}).then(function() {
console.log('12')
})
})
1.整体script作为第一个宏任务进入主线程,遇到console.log(1)输出1
遇到setTimeout, 其回调函数被分发到宏任务event queue中。我们暂且记为setTimeout1
3.遇到process.nextTick(),其回调函数被分发到微任务event queue中,我们记为process1
4.遇到Promise, new Promise直接执行,输出7.then被分发到微任务event queue中,我们记为then1
又遇到setTimeout,其回调函数被分发到宏任务event queue中,我们记为setTimeout2.
现在开始执行微任务, 我们发现了process1和then1两个微任务,执行process1,输出6,执行then1,输出8, 第一轮事件循环正式结束, 这一轮的结果输出1,7,6,8.那么第二轮事件循环从setTimeout1宏任务开始
5. 首先输出2, 接下来遇到了process.nextTick(),统一被分发到微任务event queue,记为process2
8new Promise立即执行,输出4,then也被分发到微任务event queue中,记为then2
6. 现在开始执行微任务,我们发现有process2和then2两个微任务可以执行输出3,5. 第二轮事件循环结束,第二轮输出2,4,3,5. 第三轮事件循环从setTimeout2哄任务开始
10。 直接输出9,跟第二轮事件循环类似,输出9,11,10,12
7. 完整输出是1,7,6,8,2,4,3,5,9,11,10,12(请注意,node环境下的事件监听依赖libuv与前端环境不完全相同,输出顺序可能会有误差)
async/await用来干什么
用来优化promise的回调问题,被称为是异步的终极解决方案
async/await内部做了什么
async函数会返回一个Promise对象,如果在函数中return一个直接量(普通变量),async会把这个直接量通过Promise.resolve()封装成Promise对象。如果你返回了promise那就以你返回的promise为准。await是在等待,等待运行的结果也就是返回值。await后面通常是一个异步操作(promise),但是这不代表await后面只能跟异步才做,await后面实际是可以接普通函数调用或者直接量。
async相当于 new Promise,await相当于then
await的等待机制
如果await后面跟的不是一个promise,那await后面表达式的运算结果就是它等到的东西,如果await后面跟的是一个promise对象,await它会’阻塞’后面的diamante,等着promise对象resolve,
然后得到resolve的值作为await表达式的运算结果。但是此"阻塞"非彼“阻塞”,这就是await必须用在async函数中的原因。
async函数调用不会造成"阻塞",它内部所有的“阻塞”都被封装在一个promise对象中异步执行(这里的阻塞理解成异步等待更合理)
async/await在使用过程中有什么规定
每个async方法都返回一个promise, await只能出现在async函数中
async/await在什么场景使用
单一的promise链并不能发现async/await的有事,但是如果需要处理由多个promise组成的then链的时候,优势就能体现出来了(Promise通过then链来解决多层回调的问题,现在又用async/awai来进一步优化它)
边栏推荐
猜你喜欢
[C语言] 平淡的日子里泛起光 初阶最后的战役
小游戏类项目 —— 五子棋游戏
[C language] please fly the detailed ability functions and arrays back to the country of light
1027打印沙漏
Record some little cheese about writing the program ~ [continue to be more ~]
第10章 3D 点云特征描述提取
The fifth Bureau, akali teaching Bureau
24.【判断是否是整数用字节判断】
三子棋
1019 digital black hole
随机推荐
重置表单
1027 print hourglass
力扣中 26.删除有序数组中的重复项 88.合并两个有序数组 和189.旋转数组
第10章 3D 点云特征描述提取
深度剖析数据在内存中的存储
In depth analysis of string -- strcpy & strncpy
boost::this_thread::sleep (boost::posix_time::microseconds (100000))报错“this_thread”:“::”左侧的符号必须是一种类型
js实现监听手机端横屏竖屏切换
Small game items - Gobang game
leetcode中面试题17.04.消失的数字 和 27.移除元素
LaTeX:导数相关符号
PCL学习第九章《采样一致性》
深度剖析 —— 结构体
[C语言]请将细碎的能力函数与数组飞回光之国
D. Insert a progression (Mathematics)
第四局 下 匹配数据分析
Let the code solve the series of "linear algebra" - find the greatest common factor of polynomials
Deep analysis of string -- strchr & strstr
图片上传
深度剖析 string —— memset & memcmp