js单线程
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
//控制台输出
script start
script end
promise1
promise2
setTimeout
js执行流程
(@知乎Miku)
- 同步和异步任务分入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
- 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
- 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
- 主线程内的任务执行为空的判定: 在js引擎中,存在一个叫monitoring process的进程,这个进程会不断的检查主线程的执 行情况,一旦为空,就会去Event Quene检查有哪些待执行的函数。
宏任务和微任务
- 宏任务: setTimeout setInterval js主代码 setImmediate(Node) requestAnimationFrame(浏览器)
- 微任务: process.nextTick Promise的then方法
宏任务和微任务的执行:
**他们都从属于异步任务,主要区别在于他们的执行顺序,Event Loop的走向和取值**
- 存在微任务的话,就执行所有的微任务
- 微任务都执行完之后,执行下一个宏任务
- 1,2以此循环
- process.nextTick(callback)类似node.js版的"setTimeout",在事件循环的下一次循环中调用 callback 回调函数
- 如果想异步任务尽可能快地执行,那就使用process.nextTick
- 根据语言规格,Promise对象的回调函数,会进入异步任务里面的“微任务”(microtask)队列
- 微任务队列追加在process.nextTick队列的后面。也属于本轮循环。所以,下面的代码总是先输出3,再输出4
process.nextTick(()=>console.log(3))
promise.resolve().then(()=>console.log(4))
//控制台输出:
//3
//4
- 需要注意,只有前一个队列完全清空后,才会执行下一个队列
process.nextTick(()=>console.log(1))
promise.resolve().then(()=>console.log(2))
process.nextTick(()=>console.log(3))
promise.resolve().then(()=>console.log(4))
//输出为
//1
//3
//2
//4
//上面的代码中,process.nextTick的回调会早执行于Promise
- 下面代码的输出顺序为:
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')
})
})
//1 7 6 8 2 4 3 5 9 11 10 12