js中的Event Loop 、宏任务、微任务

in js with 0 comment views: 1,999 times

为什么要有Event Loop?

因为Javascript设计之初就是一门单线程语言,因此为了实现主线程的不阻塞,Event Loop这样的方案应运而生。

console.log(1)

setTimeout(() => {
  console.log(2)
}, 0)

Promise.resolve().then(() => {
    console.log(3)
}).then(() => {
    console.log(4)
})

console.log(5)

打印结果是 1,5,3,4,2

分析:html 规范中提炼的关键步骤如下

多出来的2个概念macro-task(宏任务)和microtask(微任务)属于对异步任务的分类,不同的API注册的异步任务会依次进入自身对应的队列中,然后等待Event Loop将它们依次压入执行栈中执行。

整个最基本的Event Loop如图所示:

image

宏任务、微任务

console.log(1)

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

new Promise(resolve => {
    console.log(7)
    resolve()
}).then(() => {
    console.log(8)
})

setTimeout(() => {
    console.log(9)
    new Promise(resolve => {
        console.log(11)
        resolve()
    }).then(() => {
        console.log(12)
    })
})

分析如下:

image

process.nextTick()

process.nextTick(callback)类似node.js版的"setTimeout",在事件循环的下一次循环中调用 callback 回调函数。

console.log(1)

setTimeout(() => {
    console.log(2)
    new Promise(resolve => {
        console.log(4)
        resolve()
    }).then(() => {
        console.log(5)
    })
    process.nextTick(() => {
        console.log(3)
    })
})

new Promise(resolve => {
    console.log(7)
    resolve()
}).then(() => {
    console.log(8)
})

process.nextTick(() => {
    console.log(6)
})

正确答案是:1、7、6、8、2、4、3、5

这说明 process.nextTick 注册的函数优先级高于Promise

console.log(1)

setTimeout(() => {
    console.log(2)
    new Promise(resolve => {
        console.log(4)
        resolve()
    }).then(() => {
        console.log(5)
    })
    process.nextTick(() => {
        console.log(3)
    })
})

new Promise(resolve => {
    console.log(7)
    resolve()
}).then(() => {
    console.log(8)
})

process.nextTick(() => {
    console.log(6)
})

setTimeout(() => {
    console.log(9)
    process.nextTick(() => {
        console.log(10)
    })
    new Promise(resolve => {
        console.log(11)
        resolve()
    }).then(() => {
        console.log(12)
    })
})

输出结果是:1、7、6、8、2、4、9、11、3、10、5、12 (这个结果环境不同,输出结果会有出入)

可以参考: https://juejin.im/post/59e85eebf265da430d571f89#heading-4 这篇文的的第五章

两次task的执行混合在一起


参考:

https://juejin.im/post/5a6155126fb9a01cb64edb45


Responses