JS的运行机制到底是什么?
先给大家来段代码,看大家能否知道输出的结果
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
了解js的同步和异步
先要明白js是单线程语言,所有的js多线程都是用单线程模拟出来的
导图要表达的内容用文字来表述的话:
- 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
- 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
- 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
我们不禁要问了,那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。
用我自己的话说:
打开一个js代码,先执行同步任务,遇到异步任务,把异步任务放到队列中,等同步任务执行完之后,在执行异步任务,非常好理解
其实这个不太准确,同步和异步是广义范围内的,如果要在精细一点,就分为宏任务和微任务,后面会讲
那些是同步?那些是异步?
异步:setTimeout(),setInterval(),Promise,process.nextTick(callback) 等
同步:剩下的基本都是同步的
宏任务和微任务
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval,dom事件,ajax请求
- micro-task(微任务):Promise,process.nextTick,asycn/await
结合图片和上面的文字可以看出
- 整个script就是一个宏任务,所以先把script放入到宏任务中
- 遇到setTimeout,setInterval,把它们也放到宏任务中。遇到Promise,process.nextTick,把它们放到微任务中
- 先执行宏任务,执行完成,执行微任务,完成之后再执行宏任务,知道把所有的任务都执行完成
接下来,看上面代码的输出结果
安装宏任务和微任务的执行顺序,一点一点来
- 把js中所有是宏任务的代码都放到宏队列中,所有的微任务都放到微队列中,能直接输出的直接输出
- 先输出1
- 遇到setTimeout(),把它放到宏任务,有两个,先标记为set1,set2
- 遇到process.nextTick,把执行的函数放到微任务
- 遇到promise,只把.then的函数放到微任务,所以输出7
- 第一步完成后输出1,7
- 然后执行微任务
- 有两个微任务,要注意先后顺序,从上到下
- 执行process.nextTick,输出6
- 执行promise.then,输出8
- 第二步完成后输出6,8
- 微任务执行完,在执行宏任务,有两个宏任务,set1,set2
- 接下来和上面的操作是一样的,先执行宏任务set1
- 输出2,4
- 把promise.then和process.nextTick放入微任务
- 执行微任务,输出3,5
- 第三步完成后输出2,4,3,5
- 再执行宏任务set2
- 输出9,11
- 把promise.then和process.nextTick放入微任务
- 执行微任务,输出10,12
- 第四步完成后输出9,11,10,12
最终结果1,7,6,8,2,4,3,5,9,11,10,12
不知道各位小伙伴答案对不对呢?