js事件执行过程
javaScript是一门单线程语言,js在执行代码时会按照代码语句的顺序执行形成一个执行栈,默认会从上到下依次执行,执行过程中会将任务分成两类。
- 同步任务:需要执行的任务在主线程上排队,一次执行
- 异步任务:没有立马执行但是需要被执行的任务,放在任务队列里面
在主线程执行过程中同步任务会立即执行,遇到异步任务时不会立马执行,会将异步任务放入一个"任务队列"(task queue)中,当"执行栈"中的所有任务执行完毕,就会去任务队列中将对应的任务事件放入执行栈中执行,主线程就是这样重复执行上面的步骤形成一个循环叫(Event Loop) 事件循环。
宏任务(MacroTask)和微任务(MicoroTask)
同步和异步分别进入到不同的执行场所,同步进入到主线程,异步的进入到event table 并注册函数,异步任务又可以分为宏任务和微任务。
常见的宏任务和微任务API
Microtask微任务
- process.nextTick
- promise
- MutationObserver
Macrotask宏任务
- 整体的script代码
- setTimeout
- setImmediate
- setInterval
- I/O
- UI 渲染
一个宏任务执行完后会立即执行该宏任务中的微任务队列,直至微任务队列清空继续执行任务队列中的下一个宏任务。
宏任务执行完会去清空微任务队列,清空微任务后如果有UI渲染逻辑会线执行UI渲染,然后执行下一下宏任务。
所以可以将事件循环,宏任务,微任务的关系用下图表示
事件循环顺序
根据上面的关系图可以总结事件执行顺序如下:
- js在执行上下文栈的同步任务执行完后
- 首先会去执行微任务队列,按照队列
先进先出
的原则,一次执行完所有Microtask微任务队列任务 - 当前微任务执行完后,判断是否有UI渲染如果有就执行渲染过程,没有就跳过
- 然后开始执行宏任务队列,一次只执行一个。执行完后检查当前微任务队列是否有任务
- 有,执行微任务队列,直至清空微任务
- 没有,执行以一个宏任务
重复循环上述步骤形成一个事件循环,可以看出各任务的执行先后关系:同步任务 > 微任务 > UI渲染 > 宏任务
下面结合这个例子分析执行顺序
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {