Web程序性能優化——Web Worker

程序性能(一)

對於大多數的前端開發者,都不會特地關注本身開發的web程序是否存在性能問題,可是在一些特殊的場景,好比遊戲,就不得不涉及性能優化的問題了。html

JavaScript發展至今,已經能夠能勝任多種開發任務,開發的程序能在多種平臺和環境運行,可是一直襬脫不了一點的是:密集型計算並非JavaScript擅長的領域。下面簡單介紹提高web程序性能的技術。前端

Web Worker

提到web開發,大多數人想到兩個關鍵次:異步、單線程。但其實單線程並非web程序惟一的運行方式,HTML5引入了一個新機制Web Worker,將多線程帶到了web開發。web

多線程程序中,一般會由於線程共享做用域和資源產生進程之間的諸多問題,這就須要線程間通訊和鎖機制,這會產生額外的開銷,而在瀏覽器中,子線程不能和主程序共享做用域,因此不會將這些問題帶到JavaScript中。ajax

示例

下面的代碼是主線程的代碼,即你的index.htmlscript標籤中的代碼,該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內部是沒法訪問主線程的任何資源的,不能訪問全局變量,不能訪問DOMBOM相關的資源,他是一個徹底獨立的線程。在chrome中,子線程也不能再開啓一個子線程。微信小程序

// 如下代碼都會報錯

alert('aaa')

document.querySelector('div')

var subWorker = new Worker('./task2.js')

複製代碼

Worker能夠執行網絡操做(ajax WebSocket)和定時器,也能夠訪問幾個重要的全局對象的複本,包括navigatorlocationJSONapplicationCache。也能夠經過importScript(..)Worker加載額外JavaScript代碼,這種加載方式是同步阻塞的,Worker會執行完加載的代碼再繼續往下執行剩餘的代碼。瀏覽器

  • Worker中重要全局對象的副本
// 如下代碼會報錯,由於Worker中的location不包含assign方法
location.assign('https://www.baidu.com')

複製代碼
  • Worker中加載額外代碼
importScripts('./task2.js')
複製代碼

Web Worker的適用場景

  • 處理密集型數學計算 能夠將UI渲染和密集型數學計算分爲兩個線程處理,提高程序性能和用戶體驗。性能優化

  • 大數據集排序前端框架

  • 數據處理(壓縮、音頻分析、圖像處理等)

  • 高流量網絡通訊

共享Worker

以前的專用Worker在同一個瀏覽器的不一樣tab中同時引用同一個js文件建立的Worker,他們之間是沒有任何關係的多份Worker複製,也不能進行通訊,而ShareWorker最重要的功能是,同個瀏覽器環境下同一站點的多個頁面實例共享同一個Worker,他們之間共享資源,能夠互相通訊。

瀏覽器對於同一主機的同時鏈接數是有限制的,尤爲是你的app須要建立長鏈接socket時,同時打開多個頁面就會打開多個socket鏈接,將這個鏈接放在中心Worker中能夠有效解決這個問題。

SharedWorker共享資源的例子,SharedWorker有不少表現和專用Worker不一樣

  • 經過port創建消息鏈接,從而得知消息來自哪一個程序。
  • port在主線程和子線程中都須要初始化。
  • 須要在Worker中監聽一次connet事件並在回調中初始化端口。
  • console.log(..)失效。
// 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.jsWebassembly入門知識將再下期介紹。

做者簡介:葉茂,蘆葦科技web前端開發工程師,表明做品:口紅挑戰網紅小遊戲、蘆葦科技官網。擅長網站建設、公衆號開發、微信小程序開發、小遊戲、公衆號開發,專一於前端框架、服務端渲染、SEO技術、交互設計、圖像繪製、數據分析等研究。

歡迎和咱們一塊兒並肩做戰: web@talkmoney.cn 訪問 www.talkmoney.cn 瞭解更多

相關文章
相關標籤/搜索