宏任务与微任务

  之前我们讨论过JS代码执行的同步和异步,JS的单线程执行机制不会改变;但是仅仅懂得同步异步是远远不够的;比如说下面这些代码:

 1 setTimeout(function(){
 2         console.log("1");
 3     });
 4     new Promise(function(resolve,reject){
 5         console.log("2");
 6         resolve();
 7     }).then(function(){
 8         console.log("3");
 9     })
10     console.log("4");

  由于同步和异步的影响,我们会自信的说出打印结果是: 2,3,4,1;可是呢,用Chrome打开运行代码,蒙了,打印的竟然是:2 ,4 ,3,1;

  这就不得不引出我们即将讨论的主角:宏任务和微任务;简单来说:JS中,大部分代码被分配到宏任务排队执行,但像Promise.then、process.nextTick()等微任务;我们就拿Promise.then来举例说明。根据先执行微任务再执行宏任务的机制;还是上面那段代码,我们简单的分析一下:

setTimeout(function(){
        console.log("1");   
    });
    new Promise(function(resolve,reject){
        console.log("2");
        resolve();
    }).then(function(){
        console.log("3");
    })
    console.log("4");

 这些代码整体作为一个宏任务开始执行,还是按照先同步,后异步的规则,遇到延时定时器,是个异步代码,先挂起来不执行;接着遇到Promise的实例化对象,属于同步任务,立即执行,打印一个2;接下来遇到实例化对象的微任务,但后面还有一个同步代码,依然是先执行同步代码,打印4;接下来一轮跑完了,我们回头看,有一个延时定时器,还有一个微任务,先执行微任务,打印出3,最后打印1;就像跑了第二遍一样,这就是一个最简单的时间循环(event Loop);

  接下来写一段稍微复杂的,读者们可以一起思考一下:

console.log('1');

    setTimeout(function () {
        console.log('2');
        new Promise(function (resolve) {
            console.log('3');
            resolve();
        }).then(function () {
            console.log('4')
        })
    })

    new Promise(function (resolve) {
        console.log('5');
        resolve();
    }).then(function () {
        console.log('6')
    })

    setTimeout(function () {
        console.log('7');
   
        new Promise(function (resolve) {
            console.log('8');
            resolve();
        }).then(function () {
            console.log('9')
        })
    })

    console.log('10');

  整段代码作为一个宏任务,先执行同步代码,所以第一次时间循环后会打印出:1,5,10;接下来发现有微任务:打印一个6;开始第二轮循环,2个异步代码并且都是立即执行的延时定时器,我们就按照从上到下的顺序执行,先看第一个定时器(此时这就是一个宏任务):会打印出2,3;然后执行微任务,打印4;最后看第二个定时器:一次打印:7,8,9;over;

  再此感谢掘金的ssssyoki大神的讲解,再加上自己的一些理解;希望这篇文章可以对你带来些许帮助;

原文地址:https://www.cnblogs.com/XieYFwin/p/10871123.html