對於大多數的前端開發者,都不會特地關注本身開發的web程序是否存在性能問題,可是在一些特殊的場景,好比遊戲,就不得不涉及性能優化的問題了。html
JavaScript
發展至今,已經能夠能勝任多種開發任務,開發的程序能在多種平臺和環境運行,可是一直襬脫不了一點的是:密集型計算並非JavaScript
擅長的領域。下面簡單介紹提高web程序性能的技術。前端
提到web開發,大多數人想到兩個關鍵次:異步、單線程。但其實單線程並非web程序惟一的運行方式,HTML5
引入了一個新機制Web Worker
,將多線程帶到了web開發。web
多線程程序中,一般會由於線程共享做用域和資源產生進程之間的諸多問題,這就須要線程間通訊和鎖機制,這會產生額外的開銷,而在瀏覽器中,子線程不能和主程序共享做用域,因此不會將這些問題帶到JavaScript
中。ajax
下面的代碼是主線程的代碼,即你的index.html
的script
標籤中的代碼,該html文件不能用文件讀取的形式直接打開,必須開啓一個web服務器打開。 子線程和主線程經過簡單的消息機制進行通信。chrome
// 實例化一個Worker
// 參數是一個url地址,應該指向的是一個js文件而不是html
var worker = new Worker('./task.js')
// 監聽子線程的消息
worker.addEventListener('message', function (e) {
console.log('message from child: ' + e.data)
})
// 向指定子線程發送消息
worker.postMessage('do some thing')
複製代碼
下面是一個子線程的示例代碼小程序
console.log('worker ready')
// 監聽來自主線程的消息
addEventListener('message', function (e) {
console.log('message from parent: ' + e.data)
})
// 向主線程發送消息
postMessage('child ready')
複製代碼
在Worker
內部是沒法訪問主線程的任何資源的,不能訪問全局變量,不能訪問DOM
和BOM
相關的資源,他是一個徹底獨立的線程。在chrome
中,子線程也不能再開啓一個子線程。微信小程序
// 如下代碼都會報錯
alert('aaa')
document.querySelector('div')
var subWorker = new Worker('./task2.js')
複製代碼
Worker
能夠執行網絡操做(ajax
WebSocket
)和定時器,也能夠訪問幾個重要的全局對象的複本,包括navigator
、location
、JSON
和applicationCache
。也能夠經過importScript(..)
向Worker
加載額外JavaScript
代碼,這種加載方式是同步阻塞的,Worker
會執行完加載的代碼再繼續往下執行剩餘的代碼。瀏覽器
// 如下代碼會報錯,由於Worker中的location不包含assign方法
location.assign('https://www.baidu.com')
複製代碼
importScripts('./task2.js')
複製代碼
處理密集型數學計算 能夠將UI渲染和密集型數學計算分爲兩個線程處理,提高程序性能和用戶體驗。性能優化
大數據集排序前端框架
數據處理(壓縮、音頻分析、圖像處理等)
高流量網絡通訊
以前的專用Worker
在同一個瀏覽器的不一樣tab中同時引用同一個js文件建立的Worker
,他們之間是沒有任何關係的多份Worker
複製,也不能進行通訊,而ShareWorker
最重要的功能是,同個瀏覽器環境下同一站點的多個頁面實例共享同一個Worker
,他們之間共享資源,能夠互相通訊。
瀏覽器對於同一主機的同時鏈接數是有限制的,尤爲是你的app須要建立長鏈接socket時,同時打開多個頁面就會打開多個socket鏈接,將這個鏈接放在中心Worker中能夠有效解決這個問題。
SharedWorker共享資源的例子,SharedWorker有不少表現和專用Worker不一樣
// index.html
var worker = new SharedWorker('./task.js')
worker.port.addEventListener('message', function (e) {
console.log('message from child: ' + e.data)
})
worker.port.postMessage('index1')
worker.port.start()
複製代碼
// task.js
var a = 1
addEventListener('connect', function (e) {
// 不會打印
console.log(e.ports)
var port = e.ports[0]
port.addEventListener('message', function () {
port.postMessage(++a)
})
port.start()
})
複製代碼
上面的代碼在打開多個index.html時,頁面實例接受到的消息是一個遞增的數值,說明了多個頁面實例公用了一個Worker而且共享了資源。
若是有某個端口鏈接終止而其餘端口仍然活躍時,共享worker不會終止。而專用Worker在它的主程序終止後就會終止。
其餘的程序性能優化技術asm.js
和Webassembly
入門知識將再下期介紹。
做者簡介:葉茂,蘆葦科技web前端開發工程師,表明做品:口紅挑戰網紅小遊戲、蘆葦科技官網。擅長網站建設、公衆號開發、微信小程序開發、小遊戲、公衆號開發,專一於前端框架、服務端渲染、SEO技術、交互設計、圖像繪製、數據分析等研究。
歡迎和咱們一塊兒並肩做戰: web@talkmoney.cn 訪問 www.talkmoney.cn 瞭解更多