WebWorker
JavaScript 中目前唯一可以實現多執行緒 (multi threads) 的功能。Web Worker 能夠讓 JavaScript 在背景執行緒 (background thread) 執行。
祐誠內心的 murmur: 依稀記得
<iframe>某種程度上也算是可以達到類似的效果。
怎麼用 Worker?
Instantiate Worker,並把要執行的 JavaScript URL 作為參數傳入。作為參數傳入的 JavaScript 會在~~異世界~~ background thread執行。
//someJavaScriptURL.js 會在異世界執行
const w = new Worker("../foldder/someJavaScriptURL.js");
-
從文章上下文推斷,此 JavaScript URL 為相對路徑。
-
Worker 中再開 Worke:可以從 Worker 中再開 Worker,而 Worker 中的 Worker 的 JavaScript URL 為 Worker 文檔的相對路徑。
-
Worker 中加載其他 js 檔案:可以透過
importScripts()API 加載 js 至 Worker Scope
Worker 不在 window 中 😱😨😰
- Worker 是執行在 worker thread 中,並非當前的網頁中,因此在 worker 的 scope 中無法取得
window。 - Worker 中的
this、self為DedicatedWorkerGlobalScope。DedicatedWorkerGlobalScope可以呼叫的 API、JavaScript Features (Methods、Type) 跟window有差異。
怎麼跟異世界通訊?postMessage()
window跟 Function 是無法透過 postMessage 傳送的。- 可以將某個 Class 的 instance 傳送過去,但會被轉成 Object,Class 上的 Function 會被吃掉。
- 傳遞的 data 是複製了一份。
- DOM 是丟不過去的~。
- postMessage 的第二個參數為
Array<Transferable>,可以把變量值的主權交給 Worker。
/* -----這邊是 Window Scope ----- */
const eureka = new Worker("eureka.js");
eureka.onmessage = function (e) {
//異世界回來的訊息會存放在 e.data 中
console.log(e.data);
}
//發送訊息給異世界
eureka.postMessage("message to another-world");
/* ------ 這邊是異世界 Scope ----- */
this.onmessage = function (e) {
//當原本的世界發送訊息到這個世界時, onmessage API 會被驅動
//原本世界發來的訊息會在 e.data 中
console.log(e.data);
}
//從異世界發訊息至原來的世界
this.postMessage("message to original-world");
// Create a 32MB "file" and fill it.
var uInt8Array = new Uint8Array(1024 * 1024 * 32); // 32MB
for (var i = 0; i < uInt8Array.length; ++i) {
uInt8Array[i] = i;
}
console.log(uInt8Array); //Uint8Array(33554432) [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, … ]
worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
console.log(uInt8Array); //Uint8Array[]
毀滅異世界的方法?terminate、close
terminate:從原本的世界毀滅異世界。close:從異世界本身結束異世界。
/* -----這邊是 Window Scope ----- */
const eureka = new Worker("eureka.js");
//異世界只是從原本世界創造出來的,其身死由我掌握哼哼哼
eureka.terminate()
/* ------ 這邊是異世界 Scope ----- */
//close === 毀滅咒語巴魯斯
this.close()
Thread Safty
The
Workerinterface spawns real OS-level threads, and mindful programmers may be concerned that concurrency can cause “interesting” effects in your code if you aren't careful.However, since web workers have carefully controlled communication points with other threads, it's actually very hard to cause concurrency problems. There's no access to non-threadsafe components or the DOM. And you have to pass specific data in and out of a thread through serialized objects. So you have to work really hard to cause problems in your code.
Content Security Policy
Worker 中的 CSP 設定是獨立的。
內嵌的 JavaScript + Worker
Solution 1 | HTML 中
//type 為 text/js-worker 的不會在頁面加載時執行
<script type="text/js-worker">
/** ... */
</script>
<script type="text/JavaScript">
const script = Array.prototype.call(
document.querySelectorAll("script[type='text\/js-worker']"),
o => o.textContent
);
const bolb = new Bolb(script, {type: "text/JavaScript"})
const worker = new Worker(window.URL.createObjectURL(bolb));
</script>
Solution 2 | JavaScript 中
function backgroundCalculate() {
/* ... */
}
const bolb = new Bolb([`(${backgroundCalculate.toString()})()`], {type: 'application/JavaScript'})
const worker = new Worker(window.URL.createObjectURL(bolb))
其他種類的 Worker
- Shared Worker
- Service Worker
- Audio Worker