写点什么

Javascript 执行机制 - 事件循环

用户头像
Sakura
关注
发布于: 2021 年 04 月 09 日

事件循环(Event Loop)

所谓的 Event Loop 就是把这些东西串联起来的一种机制,因为这东西各有理解,比如两位前端大牛之间就有分歧。阮一峰:JavaScript 运行机制详解:再谈Event Loop朴灵:朴灵评注我看过他们很多的博客和书籍,对我帮助都很大,我就用自己的看法讲讲我眼中的 Event Loop。

1,所有的任务都被放主线程上运行形成一个执行栈(execution context stack),其中的方法入参变量保存在栈内存中,复杂结构对象被保存在堆内存中;


2,同步任务直接执行并阻塞后续任务等待结束,其中遇到一些异步任务会新开线程去执行该任务(如上面提到的定时器触发线程,异步 http 请求线程等)然后往下执行,异步任务执行完返回结果之后就把回调事件加入到任务队列(Queue)


3,当执行栈(execution context stack)所有任务执行完之后,会到任务队列(Queue)里提取所有的微任务队列(micro tasks)事件执行完;


4,一次循环结束,GUI 渲染线程接管检查,重新渲染界面;


5,执行栈(execution context stack)宏任务队列(macro tasks)提取一个事件到执行,接着主线程就一直重复第 3 步;


大概理解就这样子,当然可能会有点偏差,欢迎指正!

特殊的定时器

我在上面线程说过

定时器触发线程:因为 JS 引擎是单线程容易阻塞,所以需要有单独线程为setTimeoutsetInterval计时并触发,同样是符合触发条件(记时完毕)被触发时会把对应任务添加到处理队列的尾部等到 JS 引擎空闲时处理;W3C 标准规定时间间隔低于 4ms 被算为 4ms。

里面有一些需要特别注意的地方:1,计时完毕只是把对应任务添加到处理队列,依然要等执行栈空闲才会去提取队列执行,这个概念很重要,切记!即使设置 0 秒也不会立马执行,因为 W3C 标准规定时间间隔低于 4ms 被算为 4ms,具体看浏览器,我个人认为不管怎样始终都会被放置到处理队列等待处理;2,setTimeout 重复执行过程中每次时间误差会影响后续执行时间,而 setInterval 是每次精确时间执行,当然这是指他们把对应任务添加到处理队列的精确性;

但是 setInterval 也有一些问题:

  • 累计效应,如果执行栈阻塞时间足够长以至于队列中已经存在多个 setInterval 的对应任务的情况,执行时间会远低于开发者期望的结果;

  • 部分浏览器(如 Safari 等)滚动过程执行 JS,容易造成卡顿和未知错误;

  • 浏览器最小化显示时 setInterval 会继续执行,但是对应任务会等到浏览器还原再一瞬间全部执行;

用户头像

Sakura

关注

还未添加个人签名 2020.09.22 加入

还未添加个人简介

评论

发布
暂无评论
Javascript执行机制-事件循环