此篇文章为学习慕课网双越老师课程所写自学笔记,如有侵权,立即删除
先看一到面试题
下面代码console.log的执行顺序
console.log(100);
setTimeout(()=>{
console.log(200);
})
setTimeout(()=>{
console.log(201);
})
Promise.resolve().then(()=>{
console.log(300);
})
console.log(400);
// 100 400 300 200
// 为什么300比200先打印
为什么300比200先打印这里就引出了宏任务和微任务
什么是宏任务和微任务
- 宏任务包括:setTimeout setInterval Ajax DOM事件
- 微任务:Promise async/await
- 微任务比宏任务的执行时间要早
event loop 和DOM渲染
用event loop执行下面代码的过程
先到call stack执行第一行代码打印Hi
执行setTimeout时候是将定时器放到webAPIs中
最后马上打印出bye
这时候就马上启用eventlog的机制,一遍一般的启用callback queue
DOM渲染的时机
其实在上面的执行过程中 我们还漏掉了一步 DOM的渲染
由图可知,同步代码全部执行完成后,call stack空闲了 就会马上进行DOM的渲染,触发了eventlop之后,我们会把cb1放到call stack里面去 有会触发DOM的渲染
为什么微任务比宏任务执行更快
先看下面一段代码
上面代码alert执行前刚好只会改变DOM的结构,但不会触发渲染只有点击alert的确定后页面才会渲染出变化
- 宏任务的发生是在DOM渲染后触发,如setTimeout
- 而微任务是在DOM渲染前触发,如Promise
看下面代码的执行过程就明白了
const $p1 = $('<p>一段文字</p>')
const $p2 = $('<p>一段文字</p>')
const $p3 = $('<p>一段文字</p>')
$('#container')
.append($p1)
.append($p2)
.append($p3)
// console.log('length',$('container').children().length);
// alert('本次 call stack 结束,DOM结构已更新,但尚未触发渲染')
Promise.resolve().then(()=>{
console.log('length1',
$('#container').children().length
);
alert('Promise then')//DOM还没有触发,点击确定就会立即触发
})
setTimeout(()=>{
console.log('length2',
$('#container').children().length);
alert('setTime out')//DOM已经渲染了
})
微任务和宏任务的根本区别
在执行setTimeout 的时候
是把定时器放到web APIs 里面
但是如果是Promise.then()的时候 会把它放到一个叫micro task queue的里面,而不是放到web APIs里面,如下图
为什么会有这个规定了
所以之前的执行步骤最终变为
- 先是将所有同步代码执行完毕后,call back清空
- 然后执行当前的微任务
- 再尝试DOM的渲染
- 最后触发Event Loop