事件循环(也叫EventLoop)
js执行是单线程执行代码,如果没有事件队列,js执行代码会被堵塞,所以需要事件队列,当js执行代码时遇到script、setTimeout、 promise、 渲染器、 用户交互事件、或引入外部链接link等微任务和宏任务时(也就是异步代码),需要将这些微任务和宏任务按照顺序放到微/宏任务队列中,当js代码从上到下全部执行完毕后,查看事件队列(eventLoop)中有没有微/宏任务,如果有,先执行微任务,清空微任务队列中的所有微任务,当清空完所有的微任务后,在执行宏任务,一个一个执行,直到所有的宏任务执行完毕。
上图执行顺序简易图:
根据下面的代码小结如下:
如果是宏任务的话 会将所有的宏任务放到队列中,一个一个宏任务执行,当执行第一个宏任务,如果宏任务里面有微任务,将宏任务里面所有的微任务清除干净,然后再会执行第二个宏任务
将所有执行栈的宏任务一次放到队列中,然后执行第一个宏任务,当执行第一个宏任务时,发现宏任务里面还有宏任务,则将里面的宏任务取出,放到队列任务中进行排队,当所有第一层的宏任务执行完毕后,则按照顺序执行第二层排好队的宏任务
将所有执行栈的微任务放到队列中,等待执行,当执行第一个微任务的时候,发现微任务里面还有微任务,则将里面的微任务取出
放到微任务队列后面排队 当所有的第一层微任务执行完成,按照排队执行里面的微任务
<button id="button"></button>
<script>
let button = document.querySelector('#button')
button.addEventListener('click', () => {
console.log('listener1');
Promise.resolve().then(() => console.log('micro task1'))
})
button.addEventListener('click', () => {
console.log('listener2');
Promise.resolve().then(() => console.log('micro task2'))
})
// button.click(); // click1() click2()
// listener1 micro task1 listener2 micro task2
Promise.resolve().then(() => {
fn()
fn2()
})
function fn() {
Promise.resolve().then(() => {
console.log('promise1')
// return Promise.resolve()
Promise.resolve().then(() => {
console.log("promise2")
})
})
}
function fn2() {
Promise.resolve().then(() => {
console.log("promise 3")
// return Promise.resolve()
Promise.resolve().then(() => {
console.log('promise4')
})
})
}
setTimeout(() => {
console.log(1)
setTimeout(() => {
console.log(2)
})
})
setTimeout(() => {
console.log(3)
setTimeout(() => {
console.log(4)
})
})
</script>
经典练习题巩固微/宏任务(想知道答案,动手敲一敲,有你意想不到的收获)
Promise.resolve().then(() => {
console.log('Promise1')
setTimeout(() => {
console.log('setTimeout2')
}, 0);
})
setTimeout(() => {
console.log('setTimeout1');
Promise.resolve().then(() => {
console.log('Promise2')
})
}, 0);
console.log(1);
async function async() {
console.log(2);
await console.log(3);//提点一下:这里的写法相当于 yield console.log(3)
// Promise.resolve(console.log(3)).then(()=>console.log(4))
console.log(4)
}
setTimeout(() => {
console.log(5);
}, 0);
const promise = new Promise((resolve, reject) => {
console.log(6);
resolve(7)
})
promise.then(res => {
console.log(res)
})
async();
console.log(8);