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

摘要:
Javascript:重新讨论Javascript的单线程机制。DOM渲染定时背景。Javascript是单线程事件驱动的。所有可见的Javascript代码都在一个线程中执行。计时器回调和AJAX回调将在适当的时间插入队列,以等待Javascript线程调度和执行。今天,我想测试DOM渲染的线程和时序。具体问题是:修改后的DOM是否会立即显示在UI中101112131415函数sleep{16varstart=newDate().getTime();21}2223setTimeout;3435对测试结果DOM的修改不会立即导致渲染,而是会在内部触发事件,并且该事件的处理程序将被插入Javascript调度队列中,用于调度执行。一个小示例要求在DOM中显示1到20的斐波那契数组。

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分钟,以这种形式递归,保证界面不至于卡死。

备注

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

免责声明:文章转载自《Javascript:再论Javascript的单线程机制 之 DOM渲染时机》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇NSLookup命令【译】在Asp.Net中操作PDF – iTextSharp 使用表格下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C# Thread线程介绍

一、基本概念 1、进程 首先打开任务管理器,查看当前运行的进程: 从任务管理器里面可以看到当前所有正在运行的进程。那么究竟什么是进程呢? 进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程...

[转]QT子线程与主线程的信号槽通信-亲测可用!

近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI。所以,网络通信端采用新开线程的方式。在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦。网上提供了很多同一线程不同类间采用信号槽通信的方式,但是并不完全适合线程间的信号槽通信,这主要体现在自定义消息的传递上。 首先我们看看一般的方式:利用信号-槽发送Qt内置的元数据类型testthre...

Python3之并发(五)---线程条件(Condition)和事件(Event)

一、线程条件Condition(条件变量) 依赖锁对象(Lock,RLock),锁对象可以通过参数传入获得,或者使用自动创建的默认锁对象当多个条件变量需要共享同一个锁时,建议传入锁对象 除了带有获取到锁的锁定池,Condition还包含一个未获取到锁的等待池,等待池中的线程处于等待阻塞状态,直到锁定池中的线程调用notify()/notifyAll()通知...

java.lang.OutOfMemoryError: unable to create new native thread问题排查以及当前系统最大进程数量

1. 问题描述 线上某应用出问题,查看日志 这一组服务器是2台,每台都有。配置为64G,使用7G,空余内存非常多 2. 问题排查 环境变化:程序迁移到新机器,新机器是CentOS 7,程序运行账号由原来的root改为work。硬件配置由32G升级为64G。首先切换到work账号,然后运行一个测试程序就是建立线程,发现只能跑2900多个,我的笔记本还能跑2...

IO与线程状态

这几天在看IO和NIO, 说IO是阻塞的,当多个IO访问服务器时,发生阻塞的时候,CPU要不停的轮询每个IO的线程,看哪个IO的阻塞解除。会浪费CPU资源。 然后我看了线程的状态分类,专门有人说过阻塞和同步是不一样的。 1、新建状态(New):新创建了一个线程对象。 2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法...

创建线程是否调用CloseHandle

关于是否在创建线程后调用Closehandle一直困惑,今天查了查,才明白。 CloseHandle关闭句柄并没有终止新创建的线程。只是表示对新创建的线程的引用不敢兴趣,系统会递减新线程的线程内核对象的使用计数。当使用计数为0的时候,系统就会释放线程内核对象。如果在主线程中没有关闭线程的句柄,始终都会保留一个引用。这样线程内核对象的引用计数就不会为0。即使...