JS事件循环(2)

101 阅读3分钟

作者:Blue_zns 链接:juejin.cn/post/689407…

JS采用单线程的事件循环方式管理异步任务,优点是简化编程模型,缺点是无法发挥CPU的全部性能(但对前端其实没影响)

什么是事件循环?

在JS中我们经常会需要"同时"进行多项工作,例如:定时器、事件、异步数据交互等,那么JS是如何管理这些任务的,又是如何确定他们的执行顺序的? 首先,所有的语言都拥有并发模型的概念,也就是说多个任务如何同时执行,大部分语言支持多线程执行,JS拥有所有语言中最简单的并发模型——JS使用单线程的"事件循环(Event Loop)"来处理多个任务的执行

简单来说,js的事件循环,每次读取一个任务,然后执行这个任务,执行完再继续获取下一个,如果暂时没有任务,就暂停执行,等待下一个任务到来;如果在执行任务的过程中有新的任务到达,也不会中断现有任务的执行,而是添加到队列的尾部等待

JS使用基于事件循环的单线程执行方式,而且是非抢断执行的(也就是说,无论发生什么,都会把当前任务执行完,不会出现执行到一半就去执行别的任务的情况)

简单易于使用,永远不会出现资源争抢的问题,不用考虑线程间同步


定时器不会立刻执行,因为它不能打断当前任务(JS是非抢断执行),所以它只能被放到队列的尾部

正在执行的任务(比如上面的console.log aaa和bbb)永远不会被打断,所有异步代码会被添加到队列等待执行

"最短x毫秒后,将任务添加到队列中",定时器的时间到了,它仅仅是开始排队罢了

就算没有你的任务,浏览器也有很多它的工作——渲染、重排、清理内存什么的


js里任务队列不只有一条,而是有两条,而且有一条还是SVIP年费白金队列

微任务(microTask):SVIP年费白金会员任务,优先于宏任务执行(但依然是非抢断的)

微任务:微任务出现比较晚,queueMicrotask、Promise和async属于微任务(当然,async就是promise)

第3步,queueMicrotask也不会立即执行,所以222也去排队了,但Promise进的是VIP队列

按照官方的设想,任务之间是不平等的,有些任务对用户体验影响大,就应该优先执行,而有些任务属于背景任务(比如定时器),晚点执行没有什么问题,所以设计了这种优先级队列的方式


那async是不是一定是按照微任务的方式执行呢?"不全是"

虽然async是异步操作,但async函数本身(也就是111所在的()=>{}),其实依然是同步执行的,除非有await出现,then不会同步执行,它才是异步的,而且是一个微任务