JS的运行机制到底是什么?

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,把它们放到微任务中
  • 先执行宏任务,执行完成,执行微任务,完成之后再执行宏任务,知道把所有的任务都执行完成

接下来,看上面代码的输出结果

安装宏任务和微任务的执行顺序,一点一点来

  1. 把js中所有是宏任务的代码都放到宏队列中,所有的微任务都放到微队列中,能直接输出的直接输出
    • 先输出1
    • 遇到setTimeout(),把它放到宏任务,有两个,先标记为set1,set2
    • 遇到process.nextTick,把执行的函数放到微任务
    • 遇到promise,只把.then的函数放到微任务,所以输出7
    • 第一步完成后输出1,7
  2. 然后执行微任务
    • 有两个微任务,要注意先后顺序,从上到下
    • 执行process.nextTick,输出6
    • 执行promise.then,输出8
    • 第二步完成后输出6,8
  3. 微任务执行完,在执行宏任务,有两个宏任务,set1,set2
    • 接下来和上面的操作是一样的,先执行宏任务set1
    • 输出2,4
    • 把promise.then和process.nextTick放入微任务
    • 执行微任务,输出3,5
    • 第三步完成后输出2,4,3,5
  4. 再执行宏任务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

不知道各位小伙伴答案对不对呢?

原文地址:https://www.cnblogs.com/bnzw/p/14755881.html