Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javascript任务调度队列机制 #25

Open
Quickeryi opened this issue Jul 18, 2017 · 1 comment
Open

javascript任务调度队列机制 #25

Quickeryi opened this issue Jul 18, 2017 · 1 comment

Comments

@Quickeryi
Copy link
Owner

Quickeryi commented Jul 18, 2017

我们都知道javascript是单线程机制,但是我们在开发过程中往往会写入很多的异步代码,那么js是如何进行任务调度的呢?

概念

首先我们必须要清楚几个概念,这对于理解任务队列很有帮助

  • macro-task:宏任务(也叫做 task queue
    • js中,属于宏任务的有以下几种:setTimeout, setInterval, setImmediate, I/O, UI rendering, requestAnimationFrame
  • micro-task:微任务
    • js中,属于微任务的有以下几种:process.nextTick, Promises.then, Object.observe, MutationObserver
  • 注意:主进程的所有同步代码会被划分为一个macro-task

调度过程

整个过程用一张图就可以清晰展示

52ba283f-1155-4fbc-ba42-f0dfe815bf55

实例

用代码说明一切

  • 例子1
step1:console.log('main1');
step2:setTimeout(function() {
    console.log('setTimeout');
}, 0);

step3:requestAnimationFrame(function () {
    console.log('requestAnimationFrame');
});

step4:new Promise(function(resolve, reject) {
    console.log('promise');
    resolve();
step5:}).then(function() {
    console.log('promise then');
});

step6:console.log('main2');

// output
main1
promise
main2
promise then
requestAnimationFrame
setTimeout
  • 例1分析:首先step1step4step6处于主线程,所以它会归入第一个macro-task-1,所以首先调用,然后开始逐个调度micro-task(即:step5),而后开始调度第二个macro-task-2(即:step3)如此循环,直至结束!

  • 例子2

step1:console.log('main1');

step2:process.nextTick(function () {
    console.log('process.nextTick1');
});

step3:setImmediate(function () {
    console.log('setImmediate');
}, 0);

step4:setTimeout(function() {
    console.log('setTimeout');
    step5:process.nextTick(function() {
        console.log('process.nextTick2');
    });
}, 0);

step6:new Promise(function(resolve, reject) {
    console.log('promise');
    resolve();
step7:}).then(function() {
    console.log('promise then');
});

step8:console.log('main2');

// output
main1
promise
main2
process.nextTick1
promise then
setTimeout
process.nextTick2
setImmediate
  • 例2分析:step1step6step8为第一个macro-task-1首先执行,然后调度第一层循环的micro-task(即:step2step7),然后调度第二个macro-task-2(即:step4),继续调度第二层循环micro-task(即:step5),最后调度最后一个macro-task-3(即:step3

小结

只有做到对js任务调度的机制了解,我们才能在开发中更好的掌控执行过程。

参考

@mackxu
Copy link

mackxu commented Jul 15, 2019

求解:在例子1中 同是宏任务为啥requestAnimationFrame 比 setTimeout 优先执行?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants