1、什么是js运行机制?
js运行机制,即事件循环机制。js是单线程执行的,这意味着同一时间内只能做一件事,但这并不是说单线程就会阻塞,而要实现单线程且非阻塞的方法就是事件循环机制。
在js中,会把任务分为同步和异步,这两者的执行环境不同,同步任务会进入主线程,异步任务会进入事件队列(EventQueue),当主线程代码执行完毕后,会去事件队列中读取对应的异步任务,并推到主线程中执行,不断重复过程,称为事件循环机制(EventLoop) 。
2、js的任务分类
js中将任务分为同步任务和异步任务两大类
同步任务:只要被系统扫描到,就会被主线程马上执行的任务(优先于所有的异步任务)
异步任务:即使被扫描到,也不会马上执行,会被放到事件队列中,等主线程任务执行完毕,系统才会召回执行
常见的异步任务
1、Promise.then() === 微任务
2、async/await === Promise语法糖 === 微任务
3、事件处理函数
4、setTimeout() 和 setInterval() === 宏任务
setTimeout(() => {
console.log(1)
}, 0)
console.log(2)
// 会先打印 2 然后打印 1
// 虽然setTimeout延迟为0,但它是一个异步任务,所以一定会在同步任务执行完后再去执行它
3、异步任务分类
异步任务又被分为宏任务和微任务
在异步任务中,有些异步任务的平均执行周期很长,这些任务就被JavaScript标记为宏任务(比如延时器setTimeout())。而平均执行周期相对较短的任务,被称为微任务(如promise.then())
异步任务的执行顺序
- 会优先执行已经存在于任务队列中的微任务
- 在所有的微任务执行完后,再去执行一个宏任务(只执行一个)
- 执行完宏任务,会再去微任务队列检查是否有新的微任务,有则全部执行
- 再回到宏任务队列执行一个宏任务
- 以此循环,整个流程就是事件循环机制(Event Loop)
4、例题分析
setTimeout(() => {
console.log("1")
}, 0) //异步任务 - 宏任务
console.log(2) //同步任务
Promise.resolve().then(() => {
console.log(3)
}) //异步任务 - 微任务
console.log(6) //同步任务
// 打印结果 2 6 3 1
分析:
代码执行顺序:
先执行同步任务—打印 2 和 6
然后进入异步队列 异步中先执行微任务—打印 3 最后执行宏任务—打印 1
上难度啦!!!
//第一个宏任务
setTimeout(() => {
console.log(1) //宏任务中的同步任务
Promise.resolve().then(() => {
console.log(7)
}) //宏任务中的微任务
}, 0) //异步任务 - 宏任务
console.log(2) //同步任务
Promise.resolve().then(() => {
console.log(3)
}) //异步任务 - 微任务
//第二个宏任务
setTimeout(() => {
console.log(8) //宏任务中的同步任务
setTimeout(() => {
console.log(5)
}, 0) //宏任务中的宏任务 第四个宏任务
}, 0)
//第三个宏任务
setTimeout(() => {
Promise.resolve().then(() => {
console.log(4)
}) //宏任务中的微任务
}, 0)
console.log(6) //同步任务
// 2 6 3 1 7 8 4 5
解析:
先执行同步任务 ----- 2 ,6
接下来去执行异步 异步中先执行微任务 ----- 3
接着执行异步的一个宏任务 ----- 1
再去执行异步的微任务 ----- 7
接着执行异步一个宏任务 ----- 8
下一个微任务 ----- 4
最后的一个宏任务 ----- 5
the end …