我们常常说js是单线程的,是指js执行引擎是单线程的,除了这个单线程,还有一个 任务队列,在执行js代码的过程中,执行引擎遇到注册的延时方法,如定时器,DOM事件, 会将这些方法交给相应的浏览器模块处理,当这些延时方法有触发条件去触发的时候, 这些延时方法会被添加至任务队列,而这些任务队列中的方法只有js的主线程空闲了才会执行, 这也就是说我们常常用的定时器定的时间参数只是一个触发条件,具体多少时间后执行其实还需要看 js主线程空闲与否
js引擎运行时,当代码开始运行的时候,会将代码,压入执行栈进行执行
function a() { b() }
function b() { c() }
function c() { console.log(c) }
a();
当执行栈遇到异步
当浏览器在执行栈执行的时候,发现有异步任务之后,会交给webapis去维护,而执行栈则继续执行后面的任务
- 倒计时结束后的setTimeout的可执行函数,被放入了回调队列
- setTimeout的可执行函数,被从回调队列中取出,再次放入了执行栈
Macrotask(宏任务)就是回调队列callback queue
这个队列的执行顺序是在清空执行栈之后
process.nextTick
promises
Object.observe
MutationObserver
setTimeout( () => {
console.log(1)
})
Promise.resolve().then( () => {
console.log(2)
Promise.resolve().then( () => {
console.log(3)
})
})
Promise.resolve().then( ()=> {
console.log(4)
})
// 结果
// 2
// 4
// 3
// 1
执行过程:
将setTimeout给push进宏任务
将then(2)push进微任务
将then(4)push进微任务
任务队列为空,取出微任务第一个then(2)压入执行栈
输出2,将then(3)push进微任务
任务队列为空,取出微任务第一个then(4)压入执行栈
输出4
任务队列为空,取出微任务第一个then(3)压入执行栈
输出3
任务队列为空,微任务也为空,取出宏任务中的setTimeout(1)
输出1