首页 > IT职业 > IT职场 > 任务队列、事件循环与定时器
js是单线程的,因为js可以操作DOM,如果多线程的话,会造成冲突的问题。
js的任务分为同步任务和异步任务。同步任务是指在主线程上依次执行的任务,形成一个执行栈。而异步任务不在主线程,在任务队列中,如网络请求,定时器等。在执行栈的任务执行完毕之后,系统会检查任务队列,看是否有可以执行的异步任务。-
而任务队列分为两种,一种是mircotask,另一种是marcotask。按照我的理解,mircotask和marcotask的区别在于mircotask的任务可以在本次循环/页面刷新前被加入到任务队列,而marcotask不可以
mircotask
marcotask
浏览器的event loops由HTML标准而不是ECMAScript定义,具体可以查看event-loop-processing-model,在这里列出比较关键的步奏
因此,eventloop分为三个阶段,执行一个marcotask,清空mircotask队列,运行render阶段
用代码验证一下
setTimeout(() => {
console.log('t0')
Promise.resolve().then(res => {
console.log('p0')
})
})
let i = 0
function raf () {
console.log(i)
document.querySelector('div').style.width = i * 20 + 'px'
Promise.resolve().then(res => console.log('p' + i))
setTimeout(() => {
console.log('t' + i)
if (i === 1) {
document.querySelector('div').style.background = 'red'
document.querySelector('div').style.height = '50px'
}
if (i === 2) {
let j = 0
while (j++ {
console.log('tp' + i)
})
})
if (++i 输出结果为t0,p0,0,p1,t1,tp1,1,p2,t2,tp2,2,p3,p4,t4,tp4,t4,tp4,4...
使用chrome dev tool的performance查看过程

在Event log选项卡,分析一下过程,可以观察到,代码执行顺序为,timer,animation frame,paint,而timer和animation frame中又会执行属于各自顺序的mircotasks。尽管在i=2的时候会阻塞代码,然而还是会执行ainmtion frame的代码。
看这篇文章就够了,The Node.js Event Loop, Timers, and process.nextTick()
nodejs的事件循环有六个阶段
每个阶段有自己的callback队列,清空了队列或被执行的callback达到最大限制,进入下一个阶段,此时会运行process.nextTick
setImmediate(() => console.log(2));
setTimeout(() => console.log(1));
Promise.resolve().then(() => console.log(4));
process.nextTick(() => console.log(3));
(() => console.log(5))(); 输出5,3,4,1,2
nodejs有四种定时器,setTimeout和setInterval算是一种类型,另外还有setImmediate和process.nextTick两种类型。他们跟mircotask如promise之间的执行顺序是怎样的呢?
有点摸不到头绪?写个代码看下结果
setTimeout(() => {
console.log('t1')
setTimeout(()=> {console.log('t3')})
setTimeout(() => console.log('t4'))
Promise.resolve(1).then(res => console.log('p3'))
setImmediate(() => {
console.log('i2')
setTimeout(() => console.log('t6'))
process.nextTick(() => {
console.log('n4')
process.nextTick(() => {
console.log('n5')
})
})
Promise.resolve(1).then(res => console.log('p4')).then(res => console.log('p5'))
})
setImmediate(() => {
console.log('i3')
setImmediate(() => console.log('i4'))
})
process.nextTick(() => console.log('n2'))
process.nextTick(() => console.log('n3'))
})
setTimeout(res => {
process.nextTick(() => console.log('n4'))
console.log('t2')
})
Promise.resolve(1).then(res => console.log('p1')).then(res => console.log('p2'))
process.nextTick(() => console.log('n1'))
setImmediate(() => {
console.log('i1')
setTimeout(() => console.log('t5'))
}) 输出结果是n1,p1,p2,t1,t2,n2,n3,n4,p3,i1,i2,i3,n4,n5,p4,p5,t3,t4,t5,t6,i4
过程如下
可以发现,promise和nexttick的任务是添加在本次循环,其他的是添加到下次循环。并且,是按照timers->nexttick->mircotask->check->nexttick->mircotask->timers这样的流程来运行
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1594/viewspace-2801311/ ,如需转载,请注明出处,否则将追究法律责任。