Event Loop、macrotask、micritask的结

2020-01-14  本文已影响0人  tangyefei

参考资料

Event Loop

JavaScript是单线程的语言,为了处理一些耗时的任务,会将任务分布到主线程和任务队列中。

一旦主线程的所有任务执行完毕,就会读取任务队列里面的任务。

macrotask vs microtask

任务队列里的任务又分macrotask和microtask,并且单独维护。

如果你需要在同步中进行异步任务,那么使用microtask;否则就使用macrotask。

执行顺序

  1. 执行主线程的任务
  2. 遇到一些非立即执行的任务,分别放到macrotask和microtask队列中。
  3. 立即执行microtask中所有的任务。
  4. 开始执行macrotask中的第一个任务,并且可能继续产生新的任务。
  5. 如果4产生了microtask,会继续执行3。
  6. 接着4开始执行下一个macrotask任务。

执行示例

例子1 then.then

考察了then.then的执行是有依赖顺序的

new Promise((resolve,reject)=>{
  console.log("1")
  resolve()
}).then(()=>{
  console.log("2")
}).then(()=>{
  console.log("3")
})
// 1,2,3
 new Promise((resolve,reject)=>{
  console.log("1")
  resolve()
}).then(()=>{
  console.log("2")
  return new Promise((resolve,reject)=>{
    console.log("3")
    resolve()
  }).then(()=>{
    console.log("4")
  }).then(()=>{
    console.log("5")
  })

}).then(()=>{
  console.log("6")
})
// 1,2,3,4,5,6

例子2 then.then + then

主要考察了then.then会被当做the.then,被插入到micro队列的末尾,从而最后执行:

Promise.resolve().then(()=>{
    console.log(1);
}).then(()=>{
    console.log(2);
});
Promise.resolve().then(()=>{
    console.log(3);
})
// 1,3,2
console.log('begin');
setTimeout(() => {
    console.log('setTimeout 1');
    Promise.resolve()
        .then(() => {
            console.log('promise 1');
            setTimeout(() => {
                console.log('setTimeout2');
            });
        })
        .then(() => {
            console.log('promise 2');
        });
    new Promise(resolve => {
        console.log('a');
        resolve();
    }).then(() => {
        console.log('b');
    });
}, 0);
console.log('end');

// begin, end, setTimeout 1, a, promise 1, b, promise 2, setTimeout2,

例子3 macro.micro > macro

考察了第一个setTimeout执行时,生成了micro(输出7),这时候可以插队到第二个setTimeout(输出3)前。

console.log(1);

setTimeout(() => {
  console.log(2);
  new Promise((resolve) => {
    console.log(6);
    resolve();
  }).then(() => {
    console.log(7);
  })
})

setTimeout(() => {
  console.log(3);
})

new Promise((resolve)=>{
  console.log(4);
  resolve();
}).then(()=>{
  console.log(5);
})
// 1,4,5,2,6,7,3

同样一个插队的例子。

console.log(1);

setTimeout(() => {
  console.log(2);
})

setTimeout(() => {
  console.log(3);
})

new Promise((resolve)=>{
  console.log(4);
  resolve();
}).then(()=>{
  console.log(5);
})

// 1 4 5 2 3

各种不讲理插队的例子。

console.log(1);

setTimeout(() => {
  console.log(2);
})

setTimeout(() => {
  console.log(3);
})

new Promise((resolve)=>{
  console.log(4);
  resolve();
}).then(()=>{
  console.log(5);
  new Promise((resolve) => {
    console.log(6);
    resolve();
  }).then(() => {
    console.log(7);
  })
})
// 1 4 5 6 7 2 3 

变着法插队的例子。

console.log(1);
setTimeout(() => {
  console.log(2);
  new Promise((resolve) => {
    console.log(6);
    resolve();
  }).then(() => {
    console.log(7);
  })
})

setTimeout(() => {
  console.log(3);
})

new Promise((resolve)=>{
  console.log(4);
  resolve();
}).then(()=>{
  console.log(5);
})
// 1 4 5 2 6 7 3

例子4 node.js下的执行

在浏览器环境应该输出1 2 3 4,实际在node.js下是1 2 4 3,可见micro不插队,要等macro都走一遍。

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

尽管如此,对于如下为什么5不是在10面前,仍旧是不理解?

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')
    })
})

// 7 6 8 2 4 9 11 3 10 5 12 
上一篇 下一篇

猜你喜欢

热点阅读