日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

《高性能JavaScript》第六章 快速响应的用户界面

發(fā)布時(shí)間:2024/9/30 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《高性能JavaScript》第六章 快速响应的用户界面 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

6.1 瀏覽器UI線程

瀏覽器UI線程:用于執(zhí)行JavaScript和更新用戶界面的進(jìn)程。UI線程的工作基于一個(gè)簡單的隊(duì)列系統(tǒng),任務(wù)會(huì)被保存到隊(duì)列中直到進(jìn)程空閑。

-------------------------------------------------------------------- 注:如果你對python感興趣,我這有個(gè)學(xué)習(xí)Python基地,里面有很多學(xué)習(xí)資料,感興趣的+Q群:895817687 --------------------------------------------------------------------<html><head><title>Browser UI Thread Example</title></head><body><button onclick="handleClick()">Click Me</button><script type="text/javascript">function handleClick(){var div = document.createElement("div");div.innerHTML = "Clicked!";document.body.appendChild(div);}</script></body></html>

6.1.1 瀏覽器限制

瀏覽器限制了JavaScript任務(wù)的運(yùn)行時(shí)間,它確保某些惡意代碼不能通過永不停止的密集操作鎖住用戶的瀏覽器或計(jì)算機(jī)。此類限制分為兩種:調(diào)用棧大小限制(第四章討論過)和長時(shí)間運(yùn)行腳本限制。

對于不同瀏覽器限制也不一樣:

IE:默認(rèn)500萬條語句;
Firefox:默認(rèn)限制10秒;
Safari:默認(rèn)限制5秒;
Chrome:沒有單獨(dú)限制,替代做法是依賴其通用崩潰檢測系統(tǒng)來處理;
Opera:沒有限制,鑒于Opera架構(gòu),運(yùn)行結(jié)束時(shí)不會(huì)導(dǎo)致系統(tǒng)不穩(wěn)定。

6.1.2 多久才算太久

單個(gè)JavaScript操作花費(fèi)的總時(shí)間不應(yīng)該超過100毫秒。這個(gè)數(shù)字源自Robert Miller在1968年的研究。如果頁面響應(yīng)超過100毫秒,用戶會(huì)感到自已與界面失去聯(lián)系。因此,限制所有的JavaScript任務(wù)在100毫秒或更短的時(shí)間內(nèi)完成,才能給用戶一個(gè)連續(xù)的體驗(yàn)。

6.2 使用定時(shí)器讓出時(shí)間片段

盡管盡了最大努力,有時(shí)也難免出現(xiàn)復(fù)雜的JavaScript任務(wù)不能在100毫秒內(nèi)完成。這時(shí)候,最理想的做法是讓出UI線程的控制權(quán),使得UI可以更新。
###6.2.1 定時(shí)器基礎(chǔ)
在JavaScript中可以使用setTimeout()和setInterval()創(chuàng)建定時(shí)器。定時(shí)器和UI線程的交互方式有助于把運(yùn)行耗時(shí)較長的腳本拆分為較短的片段。

注意:定時(shí)器傳入的時(shí)間參數(shù)表示任務(wù)被添加到UI線程的時(shí)間,而不是一定會(huì)在這段時(shí)間后執(zhí)行,它會(huì)在隊(duì)列中等待其他前面所有任務(wù)執(zhí)行完畢才會(huì)執(zhí)行。

var button = document.getElementById("my-button");button.onclick = function(){oneMethod();setTimeout(function(){document.getElementById("notice").style.color = "red";}, 250);};

注意:定時(shí)器代碼只有在創(chuàng)建它的函數(shù)執(zhí)行完成之后,才有可能被執(zhí)行。

var button = document.getElementById("my-button");button.onclick = function(){oneMethod();setTimeout(function(){document.getElementById("notice").style.color = "red";}, 50); anotherMethod();};

6.2.2 定時(shí)器的精度

JavaScript定時(shí)器的延遲通常不太精準(zhǔn),相差大約幾毫秒。正因?yàn)槿绱?#xff0c;定時(shí)器不能用于測量實(shí)際時(shí)間。設(shè)置定時(shí)器延遲小于15毫秒會(huì)導(dǎo)致IE鎖定,所以延遲的最小值建議設(shè)為25毫秒,以確保至少有15毫秒延遲。

6.2.3 使用定時(shí)器處理數(shù)組

在之前討論的循環(huán)優(yōu)化技術(shù)使用后,還不能滿足性能要求的時(shí)候,下一步優(yōu)化就是選用定時(shí)器。它的基本方法是把循環(huán)工作分解到一系列定時(shí)器中。
是否可以用定時(shí)器取代循環(huán)的兩個(gè)決定性因素:

1:處理過程是否必須同步?
2:數(shù)據(jù)是否必須按順序處理?
如果這兩個(gè)答案都是:否,那么代碼將適用于定時(shí)器分解任務(wù)。

function processArray(items, process, callback){var todo = items.concat(); // 克隆原數(shù)組setTimeout(function(){process(todo.shift()); // 取得數(shù)組的下一個(gè)元素并進(jìn)行處理if (todo.length > 0){ // 如果還有需要處理的元素,創(chuàng)建新的定時(shí)器setTimeout(arguments.callee, 25); // arguments.callee該值指向當(dāng)前運(yùn)行的匿名函數(shù)} else {callback(items);}}, 25);} // 使用var items = [123, 789, 323, 778, 232, 654, 219, 543, 321, 160];function outputValue(value){console.log(value);}processArray(items, outputValue, function(){console.log("Done!");});

注意:使用定時(shí)器的副作用是處理數(shù)組的總時(shí)長增加了,但為了避免鎖定瀏覽器給用戶帶來不好的體驗(yàn),這種取舍是必要的。

6.2.4 分割任務(wù)

我們通常會(huì)把一個(gè)復(fù)雜的任務(wù)分解成一系列子任務(wù)。

function saveDocument(id){// 保存文檔openDocument(id)writeText(id);closeDocument(id);// 將成功信息更新至頁面updateUI(id);} function multistep(steps, args, callback){var tasks = steps.concat(); // 克隆數(shù)組setTimeout(function(){// 執(zhí)行下一個(gè)任務(wù)var task = tasks.shift();task.apply(null, args || []);// 檢查是否還有其他任務(wù) if (tasks.length > 0){setTimeout(arguments.callee, 25);} else {callback();}}, 25);} // 使用function saveDocument(id){var tasks = [openDocument, writeText, closeDocument, updateUI];multistep(tasks, [id], function(){alert("Save completed!");});}

6.2.5 記錄代碼運(yùn)行時(shí)間

有時(shí)每次只執(zhí)行一個(gè)任務(wù)的效率不高。如果每次定時(shí)器只處理一項(xiàng),且每項(xiàng)之間產(chǎn)生25毫秒的延遲,這對性能來說是個(gè)浪費(fèi)。如果每個(gè)定時(shí)器能批處理多個(gè)任務(wù),那么效率就上來了。
還記得前面討論過JavaScript連續(xù)運(yùn)行100毫秒,不會(huì)影響用戶體驗(yàn)。建議把這個(gè)數(shù)字減半,不讓JavaScript代碼持續(xù)運(yùn)行50毫秒,這樣確保代碼永遠(yuǎn)不會(huì)影響用戶體驗(yàn)。

function timedProcessArray(items, process, callback){var todo = items.concat(); // 克隆原始數(shù)組setTimeout(function(){var start = +new Date(); // +可以把Date轉(zhuǎn)換成數(shù)字,方便計(jì)算do {process(todo.shift());} while (todo.length > 0 && (+new Date() - start < 50));if (todo.length > 0){setTimeout(arguments.callee, 25);} else {callback(items);} }, 25);}

該函數(shù)增加了一個(gè)do-while循環(huán),保證一個(gè)定時(shí)器里任務(wù)總耗時(shí)不超過50毫秒,既增加了效率有不影響用戶體驗(yàn)。

6.2.6 定時(shí)器與性能

定時(shí)器會(huì)讓JavaScript的代碼整體性能發(fā)生翻天覆地的變化,但過度使用也會(huì)對性能造成負(fù)面影響。保證同一時(shí)間只有一個(gè)定時(shí)器存在,才能避免定時(shí)器導(dǎo)致的性能問題。

6.3 Web Workers

自JavaScript誕生以來,還沒有辦法在瀏覽器UI線程外運(yùn)行代碼。Web Workers改變了這一狀況,它引入了一個(gè)接口,能使代碼運(yùn)行且不占用瀏覽器UI線程時(shí)間。

6.3.1 Worker運(yùn)行環(huán)境

由于Web Workers沒有綁定UI線程,意味著它們不能訪問瀏覽器的許多資源。Web Workers從外部線程中修改DOM會(huì)導(dǎo)致用戶界面出現(xiàn)錯(cuò)誤,但是每個(gè)Web Worker都有自己的全局運(yùn)行環(huán)境:

1:一個(gè)navigator對象,只包含四個(gè)屬性:appName,appVersion,userAgent,和platform;
2:一個(gè)location對象(和window里的一樣,只是所有屬性都是只讀的);
3:一個(gè)self對象指向全局worker對象;
4:一個(gè)importScripts()方法,使工人線程可以加載外部 JavaScript 文件;
5:所有ECMAScript對象,諸如Object,Array,Data,等等;
6:XMLHttpRequest構(gòu)造器;
7:setTimeout()和setInterval()方法;
8:close()方法可立即Worker運(yùn)行。
由于Web Workers有著不同的全局運(yùn)行環(huán)境,因此無法從JavaScript代碼中創(chuàng)建。需要?jiǎng)?chuàng)建一個(gè)完全獨(dú)立的JavaScript文件,包含了需要在Worker中運(yùn)行的代碼。然后引入這個(gè)文件:

var worker = new Worker(“code.js”);

此代碼一旦執(zhí)行,將為這個(gè)文件創(chuàng)建一個(gè)新的線程和一個(gè)新的Worker運(yùn)行環(huán)境。該文件會(huì)被異步下載,直到文件下載并執(zhí)行完成后才會(huì)啟動(dòng)Worker。

6.3.2 與Worker通信

Worker與網(wǎng)頁代碼通過事件接口進(jìn)行通信。網(wǎng)頁代碼通過postMessage()方法給Worker傳遞數(shù)據(jù);Worker有一個(gè)onmessage事件處理器接收信息,并可以用自己的postMessage()方法把數(shù)據(jù)傳回網(wǎng)頁代碼。

// 網(wǎng)頁代碼var worker = new Worker("code.js");worker.onmessage = function(event){alert(event.data);};worker.postMessage("Nicholas");// code.js內(nèi)部代碼self.onmessage = function(event){self.postMessage("Hello, " + event.data + "!");};

注意:消息系統(tǒng)是網(wǎng)頁和Worker通信的唯一途徑。

6.3.3 加載外部文件

Worker通過importScripts()方法加載外部JavaScript文件,該方法接收一個(gè)或多個(gè)JavaScript文件URL作為參數(shù)。

// code.js內(nèi)部代碼importScripts("file1.js", "file2.js");self.onmessage = function(event){self.postMessage("Hello, " + event.data + "!");};

6.3.4 實(shí)際應(yīng)用

Web Workers適用于哪些處理純數(shù)據(jù),或者與瀏覽器UI無關(guān)的長時(shí)間運(yùn)行腳本。比如:

1:編碼/解碼大字符串;
2:復(fù)雜數(shù)學(xué)運(yùn)算(包括圖像或視頻處理);
3:大數(shù)組排序。

性能優(yōu)化:任何超過100毫秒的處理過程,都應(yīng)考慮Worker方案而不是定時(shí)器方案。前提是瀏覽器支持Web Workers。

總結(jié)

以上是生活随笔為你收集整理的《高性能JavaScript》第六章 快速响应的用户界面的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。