## js引擎与GUI引擎是互斥的
[setTimeout 的黑魔法 - 李三思 - 博客园](http://www.cnblogs.com/fly-snow/p/5427865.html)
> js引擎与GUI引擎是互斥的
怎么证明,浏览器的js线程和GUI渲染线程是互斥的呢?很简单:
```html
var main = document.getElementById('main');
var newNode = document.createElement("div");
newNode.className = 'book';
main.appendChild(newNode);
while(true){}
```
js主线程死循环,一直被占用,所以GUI线程没机会运行,所以页面看不到节点插入。
**深入试验**
```html
var arr = [1,2,3,4,5,6];
for (var i in arr) {
alert(i);
console.log('i:', i);
var newNode = document.createElement("div");
newNode.className = 'book';
main.appendChild(newNode);
}
// 这样是实现不了那种效果的,你看到的alert(弹出来一个,你点下确定,插入一个)只是一种错觉假象,你看alert并没有阻塞控制台,说明其实不管你点不点,alert并没有阻塞js主进程,它只是阻塞了渲染进程而已。
// 抱歉上面是猜想,不对,下面试验过了才对
// 可以实现那种效果(点一下,插入一个DOM,控制台输出一下),控制台被阻塞了,alert会阻塞js的主进程,但是很奇怪,既然阻塞了js的主线程,即js进程没有结束,那么GUI进程此时应该互斥啊,怎么会出现插入效果呢,应该是阻塞完控制台,完后最后才渲染啊,所以这个alert有点特殊,不是你想的那种阻塞,你把alert放在循环外就知道了,它其实并没有阻塞js主进程,点下插入和控制台的效果都是假象。
参见:[JS学习笔记(一)——JS的阻塞特性 - MeteorSeed - 博客园](http://www.cnblogs.com/MeteorSeed/articles/2283629.html)
----------
var arr = [1,2,3,4,5,6];
for (var i in arr) {
setTimeout(function () {
console.log('i:', i);
var newNode = document.createElement("div");
newNode.className = 'book';
main.appendChild(newNode);
}, 1000);
}
这样也是实现不了那种效果的,这样js主线程可以在瞬间执行完,插入动作都被定时器堆积到事件队列了,最终约1秒后也是瞬间循环完事件队列,所以也是看到一下子全部插入的。
---------
改进版
var arr = [1,2,3,4,5,6];
for (var i in arr) {
setTimeout(function () {
console.log('i:', i);
var newNode = document.createElement("div");
newNode.className = 'book';
main.appendChild(newNode);
}, 1000 * i);
}
这样可以实现那种效果,因为这样就不会发生事件堆积了,中间隔开了一秒。
```
所以我们平常实现运算出一个结果就插入一个节点(一般是消息应用,那种效果能增强体验感,而不是一下子插入那么生硬,让人感觉实体是一个个插入的),那种节点一个一个插入实际上是假效果,运算在js主线程中很快就会完成,运算完成后才会轮到js渲染线程插入节点,所以我们看到的效果就是所有节点一下子几乎同时插入显示的就是因为这个原因。
lazyFade库可以模拟那种效果。
所以正真做到,在循环中,循环一个插入一个是不可能的,不可能实时的,因为 js引擎与GUI引擎互斥 所以实际情况并不是我们想的那样的,不过这样没什么,这是因为浏览器决定的,确实想要那种视觉效果,可以使用lazyFade或者上面说的方法实现。(注意没有,这里我开始说视觉效果了,而不是真实效果了,因为我们已经知道真实效果在浏览器中不存在,我们只能面对现实,接收显示,模拟出视觉效果,自己骗自己,穷开心而已)
### 参考
- [JS学习笔记(一)——JS的阻塞特性 - MeteorSeed - 博客园](http://www.cnblogs.com/MeteorSeed/articles/2283629.html)
- [关于javascript你要知道的](https://www.kancloud.cn/xiak/quanduan/369159)
- [你真的了解script标签吗?](https://www.kancloud.cn/xiak/quanduan/278616)
- [浏览器的 16ms 渲染帧](http://www.tuicool.com/articles/iyI7Rve)
- [window.requestAnimationFrame - Web API 接口 | MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame)
- [JavaScript 运行机制详解:再谈Event Loop - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2014/10/event-loop.html)
- [Javascript高性能动画与页面渲染](http://www.infoq.com/cn/articles/javascript-high-performance-animation-and-page-rendering/)
```html
看看下面这样一段代码:
function jank(second) {
var start = +new Date();
while (start + second * 1000 > (+new Date())) {}
}
div.style.backgroundColor = "red";
// some long run task
jank(5);
div.style.backgroundColor = "blue";
无论在任何的浏览器中运行上面的代码,你都不会看到div变为红色,页面通常会在假死5秒,然后容器变为蓝色。这是因为浏览器的始终只有一个线程在运行(可以这么理解,因为js引擎与UI引擎互斥)。虽然你告诉浏览器此时div背景颜色应该为红色,但是它此时还在执行脚本,无法调用UI线程。
```
- [16毫秒的优化——Web前端性能优化的微观分析 - MBA智库文档](http://doc.mbalib.com/view/31010c7871f2c899e48d6d782543cf88.html)
- [使用requestAnimationFrame实现js动画性能好_javascript技巧_脚本之家](http://www.jb51.net/article/70678.htm)
- [CSS3动画那么强,requestAnimationFrame还有毛线用? « 张鑫旭-鑫空间-鑫生活](http://www.zhangxinxu.com/wordpress/2013/09/css3-animation-requestanimationframe-tween-动画算法/)
### 扩展
test.html
```html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta name="keywords" content="keywords">
<meta name="description" content="description">
<link href="favicon.ico" rel="icon" type="image/x-icon">
<link href="" type="text/css" rel="stylesheet">
<script src=""></script>
<title>Document</title>
<style>
.book {
width: 200px;
height: 50px;
background: red;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="main"></div>
<script>
var o = true;
var main = document.getElementById('main');
(function() {
var i = 0;
var i2 = 0;
// setTimeout(function () {
// i++;
// console.log('i:', i);
// var newNode = document.createElement("div");
// newNode.className = 'book';
// main.appendChild(newNode);
// setTimeout(function () {
// i++;
// console.log('i:', i);
// var newNode = document.createElement("div");
// newNode.className = 'book';
// main.appendChild(newNode);
// }, 1000);
// }, 1000);
// var newNode = document.createElement("div");
// newNode.className = 'book';
// main.appendChild(newNode);
// while(true){}
// while (o && i2 < 10) {
// setTimeout(function () {
// i2++;
// console.log('i2:', i2);
// var newNode = document.createElement("div");
// newNode.className = 'book';
// main.appendChild(newNode);
// }, 1000);
// }
}());
</script>
</body>
</html>
```
last update:2017-9-2 12:18:02
- 开始
- 微信小程序
- 获取用户信息
- 记录
- HTML
- HTML5
- 文档根节点
- 你真的了解script标签吗?
- 文档结构
- 已经落后的技术
- form表单
- html实体
- CSS
- css优先级 & 设计模式
- 如何编写高效的 CSS 选择符
- 笔记
- 小计
- flex布局
- 细节体验
- Flex
- Grid
- tailwindcss
- JavaScript
- javascript物语
- js函数定义
- js中的数组对象
- js的json解析
- js中数组的操作
- js事件冒泡
- js中的判断
- js语句声明会提前
- cookie操作
- 关于javascript你要知道的
- 关于innerHTML的试验
- js引擎与GUI引擎是互斥的
- 如何安全的修改对象
- 当渲染引擎遇上强迫症
- 不要使用连相等
- 修改数组-对象
- 算法-函数
- 事件探析
- 事件循环
- js事件循环中的上下文和作用域的经典问题
- Promise
- 最佳实践
- 页面遮罩加载效果
- 网站静态文件之思考
- 图片加载问题
- 路由及转场解决方案
- web app
- 写一个页面路由转场的管理工具
- 谈编程
- 技术/思想的斗争
- 前端技术选型分析
- 我想放点html模板代码
- 开发自适应网页
- 后台前端项目的开发
- 网站PC版和移动版的模板方案
- 前后端分离
- 淘宝前后端分离
- 前后端分离的思考与实践(一)
- 前后端分离的思考与实践(二)
- 前后端分离的思考与实践(三)
- 前后端分离的思考与实践(四)
- 前后端分离的思考与实践(五)
- 前后端分离的思考与实践(六)
- 动画
- 开发小技巧
- Axios
- 屏幕适配
- 理论基础
- 思考
- flexible.js原理
- 实验
- rem的坑,为什么要设置成百分比,为什么又是62.5%
- 为什么以一个标准适配的,其它宽度也能同等适配
- 自适应、响应式、弹性布局、屏幕适配
- 适配:都用百分比?
- 番外篇
- 给你看看0.5px长什么样?
- 用事实证明viewport scale缩放不会改变rem元素的大小
- 为什么PC端页面缩放不会影响rem元素
- 究竟以哪个为设备独立像素
- PC到移动端初试
- 深入理解px
- 响应式之栅格系统
- 深入理解px(二)
- 一篇搞定移动端适配
- flex版栅格布局
- 其他
- 浏览器加载初探
- 警惕你的开发工具
- JS模块化
- webpack
- 打包原理
- 异步加载
- gulp
- 命名规范
- 接口开发
- sea.js学习
- require.js学习
- react学习
- react笔记
- vue学习
- vue3
- 工具、技巧
- 临时笔记
- 怎么维护好开源项目
- 待办
- 对前端MVV*C框架的思考
- jquery问题
- 临时
- 好文
- 节流防抖