Fork me on GitHub
Javascript:再论Javascript的单线程机制 之 DOM渲染时机

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

背景

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>
复制代码

测试结果

DOM的修改不会立马导致渲染,而是会内部触发一个事件(可能叫paint),这个事件的处理程序会被插入到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分钟,以这种形式递归,保证界面不至于卡死。

备注

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

posted on 2013-08-09 10:31  HackerVirus  阅读(201)  评论(0编辑  收藏  举报