JavaScript多線程-Web Worker

JS組成

ECMAScript

ECMAScript規定了JavaScript腳本的核心語法,如 數據類型、關鍵字、保留字、運算符、對象和語句等,它不屬於任何瀏覽器。javascript

Document Object Model

文檔對象模型(DOM)將web頁面與到腳本或編程語言鏈接起來。一般是指 JavaScript,但將HTMLSVGXML文檔建模爲對象並非JavaScript語言的一部分。DOM模型用一個邏輯樹來表示一個文檔,樹的每一個分支的終點都是一個節點(node),每一個節點都包含着對象(objects)。DOM的方法(methods)讓你能夠用特定方式操做這個樹,用這些方法你能夠改變文檔的結構、樣式或者內容。節點能夠關聯上事件處理器,一旦某一事件被觸發了,那些事件處理器就會被執行。java

Browser Object Model

瀏覽器對象模型(BOM),是用於描述這種對象與對象之間層次關係的模型,瀏覽器對象模型提供了獨立於內容的、能夠與瀏覽器窗口進行互動的對象結構。BOM由多個對象組成,其中表明瀏覽器窗口的Window對象是BOM的頂層對象,其餘對象都是該對象的子對象.node

線程與進程

進程(Process)是系統資源分配和調度的單元。一個運行着的程序就對應了一個進程。一個進程包括了運行中的程序和程序所使用到的內存和系統資源。若是是單核CPU的話,在同一時間內,有且只有一個進程在運行。可是,單核CPU也能實現多任務同時運行,好比你邊聽網易雲音樂的每日推薦歌曲,邊在網易有道雲筆記上寫博文。這算開了兩個進程(多進程),那運行的機制就是一下子播放一下歌,一下子響應一下你的打字,但因爲CPU切換的速度很快,你根本感受不到,以致於你認爲這兩個進程是在同時運行的。進程之間是資源隔離的。web

那線程(Thread)是什麼?線程是進程下的執行者,一個進程至少會開啓一個線程(主線程),也能夠開啓多個線程。好比網易雲音樂一邊播放音頻,一邊顯示歌詞。多進程的運行其實也就是經過進程中的線程來執行的。一個進程下的線程是能夠共享資源的,因此在多線程的狀況下,須要特別注意對臨界資源的訪問控制.算法

瀏覽器

目前最爲流行的瀏覽器爲:`Chrome,IE,Safari,FireFox,Opera.
一個瀏覽器一般由如下幾個常駐的線程:
  • 渲染引擎線程:負責頁面的渲染
  • JS引擎線程:負責JS的解析和執行
  • 定時觸發器線程:處理定時事件,好比setTimeout, setInterval
  • 事件觸發線程:處理DOM事件
  • 異步http請求線程:處理http請求
須要注意的是,渲染線程和 JS引擎線程是不能同時進行的。渲染線程在執行任務的時候, JS引擎線程會被掛起。由於 JS能夠操做DOM,若在渲染中 JS處理了 DOM,瀏覽器可能就懵逼了。

Web Worker

簡介

Web Worker (工做線程) 是 HTML5 中提出的概念,Web Workers 使得一個Web應用程序能夠在與主執行線程分離的後臺線程中運行一個腳本操做。這樣作的好處是能夠在一個單獨的線程中執行費時的處理任務,從而容許主(一般是UI)線程運行而不被阻塞/放慢.編程

Web Worker能夠分爲一下幾類:canvas

  • 專用線程(Dedicated Worker)
專用線程僅能被建立它的腳本所使用(一個專用線程對應一個主線程)
  • 共享線程(Shared Worker)
共享線程可以在不一樣的腳本中使用(一個共享線程對應多個主線程)
  • 服務工做線程(Service Workers)
註冊在指定源和路徑下的事件驅動 worker, 能夠控制關聯的頁面或者網站,攔截並修改訪問和資源請求,細粒度地緩存資源.
  • Chrome Workers
一種僅適用於 firefoxworker.
  • Aduio Workers
能夠在網絡 worker上下文中直接完成腳本化音頻處理

瀏覽器兼容性

能夠經過 caniuse 查看兼容性
  • Dedicated Worker 兼容性

圖片描述

  • Shared Worker 兼容性

圖片描述

使用場景

  • 懶加載
  • 文本分析
  • 流媒體數據處理
  • canvas圖形繪製
  • 圖像處理
  • ...

限制

  • 同源限制
  • 沒法訪問DOM
  • 有本身的上下文,沒法使用Window對象
workerType 上下文
Dedicated Worker DedicatedWorkerGlobalScope
Shared Worker SharedWorkerGlobalScope
建立線程
  • 檢查瀏覽器是否支持
if (window.Worker) {
    // some code
}
  • 專用線程
@params {String} url 表示worker將執行的腳本的URL,必須遵照同源策略
@params {Object} [options] 建立對象實例時設置的選項屬性的對象
@params {Object} [options.type]
@params {Object} [options.name]
@params {Object} [options.credentials]
@returns 建立的worker
const myWorker = new Worker(url[, options]);
  • 示例
// main.js
const myDedicatedWorker = new Worker('./dedicated_worker/worker.js', { name: 'dedicatedWorker' });

// worker.js
console.log('success');
  • 共享線程
@params {String} url 表示worker將執行的腳本的URL,必須遵照同源策略
@params {Object} [options] 建立對象實例時設置的選項屬性的對象
@params {Object} [options.type]
@params {Object} [options.name]
@params {Object} [options.credentials]
@returns 建立的worker
const myWorker = new SharedWorker(url[, options]);
  • 示例
// main.js
const mySharedWorker = new SharedWorker('./shared_worker/worker.js', { name: 'sharedWorker' });

// worker.js
console.log('success');
線程通訊
  • 發送信息
@params {Object} message 傳遞的數據對象
@params {Object} [options] 一個可選的Transferable對象的數組,用於傳遞全部權.若是一個對象的全部權被轉移,在發送它的上下文中將變爲不可用(停止),而且只有在它被髮送到的worker中可用。
myWorker.postMessage(message, transferList);
  • 接收信息
myWorker.onmessage = function(event) {
    const data = event.data; // 接收到的消息數據
}
  • 專用線程示例
// main.js
const myWorker = new Worker('worker.js');
myWorker.postMessage([10, 20]);
myWorker.onmessage = function (event) {
    console.log(event.data);
}

// worker.js
onmessage(event) {
    console.log(event.data);
    postMessage(event.data[1] - event.data[0]);
}
  • 共享線程示例
// main.js
const myWorker = new SharedWorker('worker.js');
myWorker.port.start();
myWorker.port.postMessage([10, 20]);
myWorker.port.onmessage = function (event) {
    console.log(event.data);
}

// worker.js
connect(event) {
    const port = event.port[0];

    port.onmessage(event) {
        port.postMessage(event.data[1] - event.data[0]);
    }
}
SharedWorker的使用中,咱們發現對於 SharedWorker實例對象,咱們須要經過 port屬性來訪問到主要方法;同時在 Worker腳本中,多了個全局的 connect()函數,同時在函數中也須要去獲取一個 port對象來進行啓動以及操做;這是由於,多頁頁面共享一個 SharedWorker線程時,在線程中須要去判斷和區,分來自不一樣頁面的信息,這是最主要的區別和緣由。

Worker線程中,selfthis都表明子線程的全局對象。對於監聽 message事件,如下的四種寫法是等同的。數組

// 寫法 1
self.addEventListener('message', function (e) {
    // ...
})

// 寫法 2
this.addEventListener('message', function (e) {
    // ...
})

// 寫法 3
addEventListener('message', function (e) {
    // ...
})

// 寫法 4
onmessage = function (e) {
    // ...
}
  • 示例

關閉線程

myWorker.terminate(); // 主線程中使用
close(); worker線程中使用(推薦)

錯誤處理

// 主線程
myWorker.onerror = function(event) {
    const lineno = event.lineno;      // 出錯的腳本名稱
    const filename = event.filename;  // 發生錯誤的行號
    const message = event.message;    // 對錯誤的描述
}
// 不能進行反序列化時觸發
myWorker.onmessageerror = function() { ... }  // 專用線程
myWorker.port.onmessageerror function() {...} // 共享線程

外部加載腳本

提供 importScript()方法,導入一條或者以上腳本到當前 worker的做用域裏.
每一個腳本中的全局對象都可以被 worker 使用.
importScript('first.js', 'second.js');

子進程

Worker能夠生成子進程瀏覽器

  • 存在同源限制
  • Worker中的URL相對於父級Woker所在位置進行解析

嵌入Worker

<script type="text/js-worker">
    onmessage = (event) => {
        postMessage(event.data + 1);
    }
</script>
<script>
    const workerScript = document.querySelector('script[type="text/js-worker"]');
    const blob = new Bolb(workerScript, { type: 'text/javascript' });
    const myWorker = new Worker(window.URL.createObjectURL(blob));
    myWorker.postMessage(1);
    myWorker.onmessage = (event) => {
        console.log('來自子線程消息:', event.data);
    }
</script>

結構化克隆算法

結構化克隆算法是由 HTML5規範定義的用於複製複雜 JavaScript對象的算法。經過來自 WorkerspostMessage()或使用 IndexedDB存儲對象時在內部使用。它經過遞歸輸入對象來構建克隆,同時保持先前訪問過的引用的映射,以免無限遍歷循環。這一過程能夠理解爲,在發送方使用相似 JSON.stringfy()的方法將參數序列化,在接收方採用類 JSON.parse()的方法反序列化。
  • Error以及Function對象是不能被結構化克隆算法複製的;若是你嘗試這樣子去作,這會致使拋出DATA_CLONE_ERR的異常
  • 沒法克隆DOM
  • 對象的某些特定參數也不會被保留緩存

    • RegExp對象的lastIndex字段不會被保留
    • 屬性描述符,setters 以及 getters(以及其餘相似元數據的功能)一樣不會被複制。例如,若是一個對象用屬性描述符標記爲 read-only,它將會被複製爲 read-write,由於這是默認的狀況下
    • 原形鏈上的屬性也不會被追蹤以及複製

Web Worker中可使用的函數和類

  • 時間相關
clearInterval()
clearTimeout()
setInterval()
setTimeout
  • Worker 相關
importScripts()
close()
postMessage()
  • 存儲相關
Cache
IndexedDB
  • 網絡相關
Fetch
WebSocket
XMLHttpRequest

更多

相關文章
相關標籤/搜索