## 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你要知道的](http://www.hmoore.net/xiak/quanduan/369159)
- [你真的了解script標簽嗎?](http://www.hmoore.net/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問題
- 臨時
- 好文
- 節流防抖