JS执行顺序 || EventLoop
Jonnzer Lv4

1.EventLoop

1
2
3
4
5
6
console.log('script start');
setTimeout(function() { // 置底进程
console.log('from setTimeout');
},0)
console.log('script end');
// 执行顺序:script start => script end => from setTimeout

2.微任务 && 宏任务

优先级:同步代码 > 微任务 > 宏任务 > 异步代码
宏任务:script , setTimeout, setInterval, setImmediate, i/0 , UI rendering ,requestAnimationFrame
微任务:process.nextTick, promise, Object.observe, MutationObserver,await

  • new Promise(fn) // 也属于微任务,执行优先级高
  • 且process.nextTick优先级大于promise.then
  • await后的async的fn 也会立刻执行 因为这是一个promise返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
console.log('1');

setTimeout(function() { // setTimeout1
console.log('2');
process.nextTick(function() { // process2
console.log('3');
})
new Promise(function(resolve) { // promise2
console.log('4');
resolve();
}).then(function() { // then2
console.log('5')
})
})
process.nextTick(function() { // process1
console.log('6');
})
new Promise(function(resolve) {
console.log('7'); // new Promise立即执行
resolve();
}).then(function() { // then1
console.log('8')
})

setTimeout(function() { // setTimeout2
console.log('9');
process.nextTick(function() { // process3
console.log('10');
})
new Promise(function(resolve) { // promise3
console.log('11');
resolve();
}).then(function() { // then3
console.log('12')
})
})

// 输出顺序 :
// 第一步:
//

执行完 1 和 7后,现在看下,身边有这些任务

宏任务Event 微任务Event Queue
setTimeout1 process1
setTimeout2 then1

现在第一轮的主线跑完了,轮到第一轮的微任务了,
所以,接下来执行的是process1和then1,也就是
1,7,6,8,

第一轮结束,
第二轮开始。

接下来是开启新的一轮eventLoop。开始查询到新的宏任务setTimeout1;

宏任务Event 微任务Event Queue
setTimeout1 process2
setTimeout2 then2
1,7,6,8,2,4,3,5

这下好了,setTimeout1宏任务完成了。
接下来,就剩setTimeout2宏任务。

宏任务Event 微任务Event Queue
process3
setTimeout2 then3

1,7,6,8,2,4,3,5,9,11,10,12

3. Vue的nextTick

异步更新内部是最重要的就是nextTick方法,它负责将异步任务加入队列和执行异步任务。
VUE 也将它暴露出来提供给用户使用。在数据修改完成后,立即获取相关DOM还没那么快更新,使用nextTick便可以解决这一问题。

watcher:每个监视者都有他们自己的id,当没有记录到对应的监视者.
即第一次进入逻辑,否则是重复的监视者,则不会进入。这一步就是实现监视者去重的点。

new Promise > MutationObserver > setImmediate > setTimeout

异步队列更新dom和数据,执行callback回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<input v-if="show" type="text" ref="myInput">

// js

data() {
show: false,
},
mounted() {
this.show = true

this.$refs.myInput.focus() // error

this.$nextTick(function() { // 获取dom的更新,成功执行
this.$refs.myInput.focus()
})
},

参考链接:
阮一峰 Event Loop
掘金
掘金2
segment
blog
promise async await
vue nextTick原理

  • 本文标题:JS执行顺序 || EventLoop
  • 本文作者:Jonnzer
  • 创建时间:2019-12-03 15:08:36
  • 本文链接:https://jonnzer.github.io/2019/12/03/JS/JS执行顺序/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论