- JS是一种
单线程
的编程语言 .一个执行栈,决定了任务的执行顺序服从先进后出
的特点. 如果有非常耗时的任务,就会造成阻塞. - 事件循环就是为了解决这种阻塞的, 实现异步的
一种机制
. - 对于异步. 我感觉是: 并不关注异步的过程.而是关注于异步的结果什么时候返回 , 并且我们可以对异步的结果进行操作.
- 因此. 把异步的操作放在另一个环境下去执行. 当前主线程的任务执行完. 通过事件循环的机制 . 再去任务队列中执行相应的回调函数进行处理.
所以. 就有任务队列的概念 . 对于异步任务又分为宏任务 与 微任务
- 宏任务(MacroTask) : script代码 . setTimeout . setInterval . I/O . UI Rendring .
- 微任务(MicroTask) : Process.nextTick(Node独有) . promise.then() ,.catch() , . finally . MutationObserver(H5新特性).
首先会清空执行栈中的任务。然后去清空微任务队列中的任务。然后执行宏任务队列中的任务,
但是它不会去清空,而是执行一个宏任务后,再去清空微任务队列。若微任务队列为空,则清空宏任务队列。
这样的机制叫做事件循环。
- 只有宏任务:
console.log('start')
setTimeout(() => {
console.log('定时器一')
}, 500)
setTimeout(() => {
console.log('定时器二')
}, 100)
setTimeout(() => {
console.log('定时器三')
}, 0)
console.log('end')
/*
start
end
定时器三
定时器二
定时器一
*/
我想的是 :
- 首先是main() 进入执行栈 . main() 中放的的所有的同步代码 .
- 定时器一二三则会放入宏任务队列 . 定时器三不用等待,直接放入任务队列中 . 0.1s后 ,定时器二加入 . 0.5后, 定时器一加入 .
- 待主线程目前的main()中的代码执行完后 , 去任务队列中执行相应的回调函数 .
- 只有微任务
console.log('start')
let p1 = new Promise((resolve) => {
console.log('承诺11')
resolve('成功一')
console.log('承诺12')
})
let p2 = new Promise((resolve) => {
console.log('承诺21')
resolve('成功二')
console.log('承诺22')
})
p2.then(res => {
console.log(res)
})
p1.then(res => {
console.log(res)
})
console.log('end')
/*
start
承诺11
承诺12
承诺21
承诺22
end
成功二
成功一
*/
- 这里和上面的一样. 但是对于promise构造函数. 是同步代码 . 而对于其确定状态后的回调函数then()是异步代码
- 微任务队列中, p2先进入对列, 优先输出p2 .
- 有宏任务,微任务
setTimeout(