事件循环机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012193330/article/details/68942008

我们知道JavaScript的一大特点就是单线程,而这个线程中拥有唯一的一个事件循环。JavaScript代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠任务队列(task queue)来搞定另外一些代码的执行。

这里写图片描述

队列数据结构

  1. 一个线程中,事件循环是唯一的,但是任务队列可以拥有多个。
  2. 任务队列又分为macro-task(宏任务)与micro-task(微任务),在最新标准中,它们被分别称为task与jobs。
  3. macro-task大概包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
  4. micro-task大概包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)
  5. setTimeout/Promise等我们称之为任务源。而进入任务队列的是他们指定的具体执行任务。
  6. 宏任务队列的执行顺序:script(整体代码)->setTimeout(setInterval同源)->setImmediate
    微任务队列的执行顺序:process.nextTick->Promise(then)

setTimeout任务的执行,也依然是借助函数调用栈来完成,并且遇到任务分发器的时候也会将任务分发到对应的队列中去。

只有当setTimeout中所有的任务执行完毕之后,才会再次开始执行微任务队列。并且清空所有的可执行微任务。

setTiemout队列产生的微任务执行完毕之后,循环则回过头来开始执行setImmediate队列。仍然是先将setImmediate队列中的任务执行完毕,再执行所产生的微任务。

当setImmediate队列执行产生的微任务全部执行之后,第二轮循环也就结束了。

大家需要注意这里的循环结束的时间节点。
当我们在执行setTimeout任务中遇到setTimeout时,它仍然会将对应的任务分发到setTimeout队列中去,但是该任务就得等到下一轮事件循环执行了。例子中没有涉及到这么复杂的嵌套,大家可以动手添加或者修改他们的位置来感受一下循环的变化。

Example1:

console.log('golb1');

setTimeout(function() {
    console.log('timeout1');
    process.nextTick(function() {
        console.log('timeout1_nextTick');
    })
    new Promise(function(resolve) {
        console.log('timeout1_promise');
        resolve();
    }).then(function() {
        console.log('timeout1_then')
    })
})

setImmediate(function() {
    console.log('immediate1');
    process.nextTick(function() {
        console.log('immediate1_nextTick');
    })
    new Promise(function(resolve) {
        console.log('immediate1_promise');
        resolve();
    }).then(function() {
        console.log('immediate1_then')
    })
})

process.nextTick(function() {
    console.log('glob1_nextTick');
})
new Promise(function(resolve) {
    console.log('glob1_promise');
    resolve();
}).then(function() {
    console.log('glob1_then')
})

setTimeout(function() {
    console.log('timeout2');
    process.nextTick(function() {
        console.log('timeout2_nextTick');
    })
    new Promise(function(resolve) {
        console.log('timeout2_promise');
        resolve();
    }).then(function() {
        console.log('timeout2_then')
    })
})

process.nextTick(function() {
    console.log('glob2_nextTick');
})
new Promise(function(resolve) {
    console.log('glob2_promise');
    resolve();
}).then(function() {
    console.log('glob2_then')
})

setImmediate(function() {
    console.log('immediate2');
    process.nextTick(function() {
        console.log('immediate2_nextTick');
    })
    new Promise(function(resolve) {
        console.log('immediate2_promise');
        resolve();
    }).then(function() {
        console.log('immediate2_then')
    })
})

这里写图片描述

这里写图片描述

Example2:

setTimeout(function() {
    console.log(1);
    setTimeout(function() {
        console.log(2);
    }, 0);
    process.nextTick(function() {
        console.log(5);
        process.nextTick(function() {
            console.log(6);
        });
    });
}, 0);
process.nextTick(function() {
    console.log(3);
    process.nextTick(function() {
        console.log(4);
    });
    setTimeout(function() {
        console.log(7);
    }, 0);
});

结果:3 4 1 7 5 6 2

参考文章:http://www.jianshu.com/p/12b9f73c5a4f

猜你喜欢

转载自blog.csdn.net/u012193330/article/details/68942008