摘要:还请同学跟我多多探讨关于修改是异步还是同步的问题先来看代码上述代码的结果完全就是同步的表现,如果是异步的话,毫无疑问,第一个下的每个内容都应该是,第二个也应该是。
回 @bf 同学
本篇文章不是笔记也不是心得,而是关于一个问题的讨论,问题最初出现于https://segmentfault.com/q/1010000005630545?_ea=903562
由于 @bf 同学不方便加QQ/微信,而这个问题又比较大,在问答评论里不好描述清楚,so,趁着周末专门写了一篇文章来回应 @bf 同学
@bf 同学,提到了一个观点:对DOM的修改永远是异步的
当时就震惊到我了(可能技术不达标,少见多怪的缘故,哈哈)
说实话,干了好几年开发,第一次明确地听到有人这样说,根据自己看的书及一些javascript编程经验来说,起初我认为是错误的。
然后看了看 @bf 同学的回复,能自圆其说,还说的头头是道,所以我真的以为对DOM的修改永远是异步的是正确的。然后怀着震惊的心情(因为跟经验相违背),还写了一篇博客记录http://www.liyanshan.com/2016/06/09/%E5%AF%B9DOM%E7%9A%84%E4%BF%AE%E6%94%B9%E6%B0%B8%E8%BF%9C%E9%83%BD%E6%98%AF%E5%BC%82%E6%AD%A5%E7%9A%84/
经过这么些天的发酵和消化,觉得对这个观点又回到了最初的认识(即这个观点是错的)。
还请 @bf 同学跟我多多探讨 !
关于javascript修改dom是异步还是同步的问题:
先来看代码:
上述代码的结果完全就是同步的表现,如果是异步的话,毫无疑问,第一个ul下的li每个内容都应该是5,第二个也应该是5。
这是数学中的反证法。即一个命题,哪怕我找出一个特例(何况我能找出很多例子)能推翻这个命题,那么这个命题就不成立。
@bf 同学可能会说了,他也用反证法,比如script标签的加载,来证明DOM修改是异步的
但是这个特例的问题在于:
把下载的异步性当成了DOM修改的异步性
script标签加载是异步的,因为要走网络(比如走网络的ajax和图片下载等都是异步的,当然ajax也可以写成同步的),也就是说,浏览器开了一个线程下载要用的script,但是马上返回(交给HTTP请求线程就不管了,请求结束,请求线程会把结果放入事件队列里),接着执行或下载其他部分。其实这个问题我在引起这个讨论的问题上已经回答了(可能回答的没有那么清楚)。
然后又陆陆续续地看了一些书,查了一些资料,问了一些大牛,越来越坚信DOM修改是同步的
JavaScript异步编程第一章 - 异步的I/O函数(1.2.1)
这个也符合我最初跟 @bf 同学的解释:修改DOM是同步的,但是渲染是异步的。因为JavaScript引擎线程跟GUI渲染线程是互斥的,即我执行的时候,你就靠边站,我执行完你才能执行
详见我2014年写的一篇关于异步的文章(当时就是记录一下心得与笔记,也不会自己搭博客,也不会MD,所以请 @bf 同学凑合看)http://blog.sina.com.cn/s/blog_6fd55a970102v64x.html
在群里提问
这个其实就相当于回答了js是同步修改的。。因为这是三个异步函数!
而 @bf 同学在后面的回复中,提到了一篇文章https://leozdgao.me/why-dom-slow/,额,我看了看这篇文章,发现其实我今年年初就看过了,当时貌似是用浏览器重排和重绘搜索到的。。
这篇文章主要是讲 重排和重绘及性能优化一类的知识。
@bf 同学可能受到这句话的影响:
一般情况下,浏览器的layout是lazy的,也就是说:在js脚本执行时,是不会去更新DOM的,任何对DOM的修改都会被暂存在一个队列中,在当前js的执行上下文完成执行后,会根据这个队列中的修改,进行一次layout。
这个其实说明不了修改DOM永远是异步的,这个是JavaScript引擎实现层面上的知识,是对js修改DOM的优化,它放入的队列其实不是事件队列,如果放到了事件队列中,才是异步的。。C++实现一个队列是何其简单啊!js实现队列更简单!只是实现层面的东西,对程序猿都是透明的。。所以没啥可说的。只能帮助我们理解重排和重绘的机制,而不能得出修改DOM永远是异步的结论。。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/79774.html
摘要:关于异步应该很多地方都说过,是单线程的,严格的说,是指引擎中负责解释和执行代码的线程只有一个,除此之外,其实还有事件触发线程请求线程等,因此,应该说同步是单线程可能更准确些。 作者:心叶时间:2019-03-08 09:45 我的理解 先列出我的理解,然后再从具体的例子中说明: DOM操作本身应该是同步的(当然,我说的是单纯的DOM操作,不考虑ajax请求后渲染等) DOM操作之后导...
摘要:根本原因在于,并不是真正意义上的异步操作,它只是模拟了异步的行为。而合成事件和生命周期函数中,是受控制的,其会将设置为,从而走的是类似异步的那一套。总结此处总结是直接引用了只在合成事件和钩子函数中是异步的,在原生事件和中都是同步的。 如何使用setState 在 React 日常的使用中,一个很重要的点就是,不要直接去修改 state。例如:this.state.count = 1是无...
摘要:主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为事件循环。上面也提到,在到达指定时间时,定时器就会将相应回调函数插入任务队列尾部。这就是定时器功能。关于定时器的重要补充定时器包括与两个方法。 一、引子 本文介绍JavaScript运行机制,这一部分比较抽象,我们先从一道面试题入手: console.log(1); setTimeout(function()...
摘要:主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为事件循环。上面也提到,在到达指定时间时,定时器就会将相应回调函数插入任务队列尾部。这就是定时器功能。关于定时器的重要补充定时器包括与两个方法。 一、引子 本文介绍JavaScript运行机制,这一部分比较抽象,我们先从一道面试题入手: console.log(1); setTimeout(function()...
摘要:主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为事件循环。上面也提到,在到达指定时间时,定时器就会将相应回调函数插入任务队列尾部。这就是定时器功能。关于定时器的重要补充定时器包括与两个方法。 一、引子 本文介绍JavaScript运行机制,这一部分比较抽象,我们先从一道面试题入手: console.log(1); setTimeout(function()...
阅读 3735·2021-11-25 09:43
阅读 2168·2021-11-23 10:13
阅读 803·2021-11-16 11:44
阅读 2345·2019-08-29 17:24
阅读 1357·2019-08-29 17:17
阅读 3464·2019-08-29 11:30
阅读 2549·2019-08-26 13:23
阅读 2328·2019-08-26 12:10