浅析js运行机制及宏任务/微任务

2020-11-25  本文已影响0人  叫维特的少年

由于最近在找工作,被问到最多的的问题之一便是js的事件循环机制了...
先来看下边的代码

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

new Promise(function(resolve) {
     console.log('promise1');
       resolve();
     console.log('promise2');
 }).then(function() {
    console.log('then');
 });

console.log('script end');

对于运行结果是跟代码的顺序是不一样的....

js运行机制

JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:

主线程的执行过程就是一个 tick,而所有的异步结果都是通过 “任务队列” 来调度。 消息队列中存放的是一个个的任务(task)。 规范中规定 task 分为两大类,分别是 宏任务(macro task) 和 微任务(micro task),并且每个 macro task 结束后,都要清空所有的 micro task。

常见的 macro task 有 setTimeout、setInterval、setImmediate
常见的 micro task 有process.nextTick(node环境)、MutationObserver 和 Promise.then/catch(promise是同步的,其回调函数是微任务)

继续分析最开始的代码
进入主执行栈的任务

//栈是先进后出,这里的代码由上到下入栈执行,执行结束由下到上出栈(不知道这样表述对不对)
console.log('script start');
console.log('promise1');
console.log('promise2');
console.log('script end');

进入异步任务队列

//队列先进先出,但微任务优先级高于宏任务
//宏任务
setTimeout(function() {
  console.log('setTimeout');
}, 0);
//微任务
promise.then(function() {
    console.log('then');
 });

由此我们可以推测打印结果是

script start
promise1
promise2
script end
then
setTimeout

当然真实的结果也是如此


结果

希望这篇文章对小伙伴能有帮助,如果其中有表述错误也希望可以指出
最后的最后,上一段代码,这是我之前遇到的面试题的升级版,当时看都看蒙了,那是一次一言难尽的经历...

console.log('1');
setTimeout(function (argument) {
    console.log('2');
    process.nextTick(function(){
        console.log('3')
    });
    new Promise(function (resolve){
          console.log('4')
          resolve()
    }).then(function (){
        console.log('5');
    })
},100);
function log(){
    return new Promise(function(resolve){
        console.log('6');
        resolve('7');
    })
}
async function async(){
    console.log('8')
    await log().then(function(res){
        console.log(res)
    })
    console.log('9');
};
new Promise(function(resolve){
        console.log('10');
        resolve();
        console.log('11');
    }).then(function (res){
        console.log('12')
    })
process.nextTick(function(){
    console.log('13')
})  
async();
setTimeout(function (argument) {
    console.log('14');
    process.nextTick(function(){
        console.log('15')
    });
    new Promise(function (resolve){
          console.log('16')
          resolve()
    }).then(function (){
        console.log('17');
    })
},0);

ps:在浏览器环境下会报错,因为浏览器环境没有process,通过node index.js运行即可,看下答案跟你的预测是否一样吧

年华如果虚度,生命将毫无意义
上一篇 下一篇

猜你喜欢

热点阅读