资讯专栏INFORMATION COLUMN

我不该动你的,Event Loops(深坑)

wenhai.he / 914人阅读

摘要:我不该动你的,写在前面的话本意是想好好研究下,看了几篇博客后,才意识到作为前端打字员的我有多无知,这坑忒深了。这样的话,如果是第一种解释,应该在运行之前,页面就变成了红色否则就应该采取第二种解释。

我不该动你的,Event Loops 写在前面的话

本意是想好好研究下 Event Loops, 看了几篇博客后,才意识到作为前端打字员的我有多无知,这坑忒深了。

macrotask?,microtask?,MutationObserver? 这些都是啥?规范还没写清楚?不同浏览器运行的还未必一样?

但为了使自己养成经常总结的习惯,还是写点什么吧。

故事的开始

  

计算 fib(45) 是一个相当耗时的工作,在我的chrome里约需要15s左右。

问,页面什么时候会变成红色?在执行 console.now(1) 之前就变成红色了吗?

可以看到即使在 console.now(1) 执行之后,页面仍旧没有变红。

关于这个现象,可以有两种解释:

document.getElementsByTagName("body")[0].style.backgroundColor = "red" 被当作一个异步事件,作为一个 task,被添加到 event loops

渲染引擎要等到 JS 引擎空闲时才开始工作

到底是哪一种?所以将上述代码修改下

又增加了一个 setTimeout。这样的话,如果是第一种解释,应该在 console.now(3) 运行之前,页面就变成了红色;否则就应该采取第二种解释。

运行结果如下,

可以看到在 console.now(3) 之后,页面依旧没有变色,看来就是渲染引擎要等到JS引擎完全空闲时才工作。

事情就这样结束了吗

没有,直到我看到文档

An event loop must continually run through the following steps for as long as it exists:

Let oldestTask be the oldest task on one of the event loop"s task queues, if any, ignoring, in the case of a browsing context event loop, tasks whose associated Documents are not fully active. The user agent may pick any task queue. If there is no task to select, then jump to the microtasks step below.

Set the event loop"s currently running task to oldestTask.

Run oldestTask.

Set the event loop"s currently running task back to null.

Remove oldestTask from its task queue.

Microtasks: Perform a microtask checkpoint.

Update the rendering: If this event loop is a browsing context event loop (as opposed to a worker event loop), then run the following substeps.

…...

这段话第7点的意思,怎么理解起来像是每执行一次 Event Loops 的 task,最后都会更新视图。

后来看到从event loop规范探究javaScript异步及浏览器更新渲染时机中

渲染更新(Update the rendering)会在event loop中的tasks和microtasks完成后进行,但并不是每轮event loop都会更新渲染,这取决于是否修改了dom和浏览器觉得是否有必要在此时立即将新状态呈现给用户。

会不会两次 setTimeout 被合并了?

这样调整之后,在运行 console.now(3) 之前,页面的颜色就变了

这样看来,就是在每一次task之后就可能会更新视图,而不是等到JS引擎空闲

在执行完setTimeout0后,Event Loops 中实际上仍有 setTimeout1 待执行,但是浏览器先渲染了视图,再执行了setTimeout ,这就推翻了之前渲染引擎要等到 JS 引擎空闲(Event Loops为空)时才开始工作。

同时我怀疑,之前代码

setTimeout(function () {
      console.now(0)
      document.getElementsByTagName("body")[0].style.backgroundColor = "red"
      console.now(1)
      fib(45)
      console.now(2)
    }, 1000)
    setTimeout(function () {
      console.now(3)
      fib(45)
      console.now(4)
    }, 1000)

会不会被优化成

setTimeout(function () {
      console.now(0)
      document.getElementsByTagName("body")[0].style.backgroundColor = "red"
      console.now(1)
      fib(45)
      console.now(2)
      console.now(3)
      fib(45)
      console.now(4)
    }, 1000)
坑深,今天先到这,休息下了 参考资料

https://github.com/aooy/blog/...

https://www.404forest.com/201...

http://javascript.ruanyifeng....

https://www.html5rocks.com/zh...

https://github.com/fredshare/...

http://lynnelv.github.io/js-e...

https://www.w3.org/TR/html5/w...

https://jakearchibald.com/201...

https://zhuanlan.zhihu.com/p/...

https://developers.google.com...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90571.html

相关文章

  • 你不得不知的Event Loop

    摘要:具体的可以用下面的图来大致说明一下同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入。主线程内的任务执行完毕为空,会去读取对应的任务,推入主线程执行。 前言 众所周知,JavaScript是一门单线程语言,虽然在html5中提出了Web-Worker,但这并未改变JavaScript是单线程这一核心。可看HTML规范中的这段话: To coordinate ...

    call_me_R 评论0 收藏0
  • event loop规范探究javaScript异步及浏览器更新渲染时机

    摘要:规范中定义了浏览器何时进行渲染更新,了解它有助于性能优化。结合一些资料,对上边规范给出一些理解有误请指正每个线程都有自己的。列为,列为,列为。我们都知道是单线程,渲染计算和脚本运行共用同一线程网络请求会有其他线程,导致脚本运行会阻塞渲染。 本文转自blog 转载请注明出处 异步的思考 event loops隐藏得比较深,很多人对它很陌生。但提起异步,相信每个人都知道。异步背后的靠山就是...

    jk_v1 评论0 收藏0
  • event loop规范探究javaScript异步及浏览器更新渲染时机

    摘要:规范中定义了浏览器何时进行渲染更新,了解它有助于性能优化。结合一些资料,对上边规范给出一些理解有误请指正每个线程都有自己的。列为,列为,列为。我们都知道是单线程,渲染计算和脚本运行共用同一线程网络请求会有其他线程,导致脚本运行会阻塞渲染。 本文转自blog 转载请注明出处 异步的思考 event loops隐藏得比较深,很多人对它很陌生。但提起异步,相信每个人都知道。异步背后的靠山就是...

    13651657101 评论0 收藏0
  • javasscript - 收藏集 - 掘金

    摘要:跨域请求详解从繁至简前端掘金什么是为什么要用是的一种使用模式,可用于解决主流浏览器的跨域数据访问的问题。异步编程入门道典型的面试题前端掘金在界中,开发人员的需求量一直居高不下。 jsonp 跨域请求详解——从繁至简 - 前端 - 掘金什么是jsonp?为什么要用jsonp?JSONP(JSON with Padding)是JSON的一种使用模式,可用于解决主流浏览器的跨域数据访问的问题...

    Rango 评论0 收藏0
  • python并发4:使用thread处理并发

    摘要:如果某线程并未使用很多操作,它会在自己的时间片内一直占用处理器和。在中使用线程在和等大多数类系统上运行时,支持多线程编程。守护线程另一个避免使用模块的原因是,它不支持守护线程。 这一篇是Python并发的第四篇,主要介绍进程和线程的定义,Python线程和全局解释器锁以及Python如何使用thread模块处理并发 引言&动机 考虑一下这个场景,我们有10000条数据需要处理,处理每条...

    joywek 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<