JavaScript中的event loop和宏任务、微任务
背景
“JavaScript 是单线程、异步、非阻塞、解释型脚本语言”
之前看到这句话会觉得很懵,不太懂是什么意思,抽空复习时候看了一下js的执行机制,这时候对这句话有了一些了解。JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生。
js遇到异步是如何执行的
- 大家都知道js中setTimeout是异步的,看下面代码执行顺序:
//1
console.log(1)
//2
setTimeout(() => {
console.log(2)
}, 1000);
//3
console.log(3)
-
首先js会输出1,然后遇到setTimeout,这时候js不会立即执行,而是发起一个异步,然后接着走到第三步,输出3,这时候执行栈为空,然后会将setTimeout的回调函数压入执行栈进行执行。所以结果为1->3->2
-
继续看代码:
console.log(1)
setTimeout(() => {
console.log(2)
}, 0);
console.log(3)
setTimeout(() => {
console.log(4)
}, 1000);
- 还是之前的代码,首先肯定会输出1,然后遇到setTimeout,注册函数,接着会输出3,然后又遇到一个setTimeout,注册函数,这时候执行栈已经没有任务,事件触发线程会从消息队列中取出刚才加入队列的函数进行执行,此时会输出2,然后执行栈又为空,这时候事件触发线程又会去消息队列中取出一个函数进行执行,此时会输出4。这就是Event-Loop。
微任务
- 都知道Pormise是微任务,下面就拿Pormise举例子:
console.log(1)
setTimeout(() => {
console.log(2)
}, 1000);
let test=new Pormise((resolve)=>{
console.log(3);
resolve();
})
.then(=>console.log(4))
console.log(5)
- 首先会输出1,然后遇到setTimeout,注册任务接着又遇到Pormise,首先先输出3,然后注册任务,接着会输出5,这时候执行栈没有可执行的,然后会从队列中取,这时候会先取出微任务进行执行,进入到then,输出4,这时候执行栈又为空,这时候继续从队列中取出一条任务,这时候会输出2。
练习
- 检测一下自己到底有木有掌握
console.log(1) //同步任务A
setTimeout( //同步任务B
() => { console.log(2) } //任务B产生的异步宏任务
, 300)
new Promise( //同步任务C
(resolve) => { console.log(3); resolve(4); }
)
.then( //任务C执行过程中resolve(4)语句产生的异步微任务
(num) => { console.log(num) }
)
setTimeout( //同步任务D
()=> { console.log(5) } //任务D产生的异步宏任务
, 800)
//1-3-4-2-5