Javascript:再论Javascript的单线程机制 之 DOM渲染时机

本文探讨了DOM修改后的渲染时机及JavaScript单线程事件驱动特性。通过具体测试案例展示了DOM更新并非即时反映,而是由独立渲染线程按队列执行。此外,还提供了一个使用递归与setTimeout结合的例子来避免页面卡顿。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

Javascript是单线程事件驱动的,所有能看到的Javascript代码都是在一个线程执行,定时器回调和AJAX回调会在适当的时刻插入队列等待Javascript线程调度执行,今天想测试一下DOM渲染的线程与时机,具体的问题是:

修改DOM会立即显示在UI中吗?

一个小测试

测试代码

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <title></title>
 6     <script src="Scripts/jquery-2.0.3.js"></script>
 7 </head>
 8 <body>
 9     <p>DOM的修改不会立马导致渲染,而是会内部触发一个事件(可能叫paint),这个事件的处理程序会被插入到Javascript的调度队列中等待调度执行。</p>
10     <div id="Test1" style="height: 100px; margin: 5px; background-color: yellow;"></div>
11 </body>
12 </html>
13 <script type="text/javascript">
14 
15     function sleep(millisecond) {
16         var start = new Date().getTime();
17 
18         do {
19             var end = new Date().getTime();
20         } while (end - start <= millisecond);
21     }
22 
23     setTimeout(function () {
24         console.log('start...');
25 
26         $("#Test1").css({
27             backgroundColor: 'red'
28         });
29 
30         sleep(3000);
31 
32         console.log('...end');
33     }, 2000);
34 
35 </script>

输出结果

start...

//两秒中CPU空转。

end...

改变了背景

注意:这里的setTimeout只是为了更好的观察效果,想想成onclick的事件处理程序就行了。

测试结果

DOM的修改不会立马导致渲染,渲染线程是在一个独立的线程运行的,但是渲染线程和Javascript线程是互斥的,必须等待Javascript的这次调度执行完或线程挂起了,才能执行渲染。

一个小例子

需求

在DOM中显示1至20的斐波那契数组。

实现

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <title></title>
 6     <script src="Scripts/jquery-2.0.3.js"></script>
 7 </head>
 8 <body>
 9 <div id="Test2" style="height: 100px; margin: 5px; background-color: blue;"></div>
10 </body>
11 </html>
12 
13 <script type="text/javascript">
14     setTimeout(function () {
15         var fibonacci = function (n, callback) {
16             if (n == 1 | n == 0) {
17                 callback(n);
18             }
19 
20             setTimeout(function () {
21                 fibonacci(n - 1, function (n_1) {
22                     fibonacci(n - 2, function (n_2) {
23                         callback(n_1 + n_2);
24                     });
25                 });
26             }, 0);
27         }
28 
29         for (var i = 1; i <= 20; i++) {
30             fibonacci(i, function (result) {
31                 $("#Test2").append(result + '<br/>');
32             });
33         }
34     }, 4000);
35 </script>

分析

如果采用传统的递归方式,界面至少卡死N分钟,以这种形式递归,保证界面不至于卡死。

备注

时刻铭记:单线程+事件驱动。

今天发现了一篇好文章:http://julying.com/blog/javascript-settimeout-thread/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值