我們知道在 HTML 使用 Javascript 大致上有兩種方式
<head> 或 <body> 中,可以插入帶有 src 的 <script> 標籤,表示從另一個檔案來源中載入執行 js
<html>
<head>
<script src="javascript.js"></script>
</head>
</html>
<script> 標籤中撰寫 js,這樣在載入 HTML 時 js 會被解析後直接執行<html>
<head>
<script>
alert("Hello World!");
</script>
</head>
</html>
那麽在使用 Web worker 的時候,是否有一個方式可以像以上第二種使用 inline script 的方式,直接將 Web worker 的程式碼寫在 HTML 檔案裡呢?
這種方式就是今天要介紹的 Embedded worker
Step 1. 在 script 標籤中塞入無效的 MIME
通常在 HTML 檔案中使用 Embedded worker 的方式,會在 <script> 標籤中塞入一個無效的 MIME 類型,例如:text/js-worker,因為是無效的 MIME 所以瀏覽器並不會把之中的程式碼解析當作 javascript 執行
<script type="text/js-worker">
// 撰寫 worker 線程的程式碼
onmessage = (event) => {
const { data } = event;
console.log('worker 接收到的訊息:', event.data);
postMessage('這是 worker 傳出去的訊息');
};
</script>
Step 2. 將 script 標籤中的程式轉換為 blob
為了能夠讓 script 中的程式之後能被 new Worker() 載入使用,需要先轉換為 blob 格式
// 另一個可以正常執行 js 的 script 標籤
<script>
// 將 text/js-worker 類型的 scripts 抓出,並轉換為 blob
const blob = new Blob(
Array.from(
document.querySelectorAll("script[type='text\/js-worker']"),
(script) => script.textContent,
),
{ type: "text/javascript" },
);
</script>
Step 3. 創建 Web worker
最後就可以使用 window.URL.createObjectURL 將 blob 轉為 url,並丟入到 new Worker() 裡創建 Web worker
const worker = new Worker(window.URL.createObjectURL(blob));
worker.postMessage('傳給 worker 的訊息');
通常當 worker 中的程式碼不多時才會考慮使用 Embedded worker,因為當牽涉複雜的邏輯時,為了維護性就會傾向把程式碼分拆到各個檔案裡撰寫,或甚至使用 module worker 的方式使共用程式碼更為方便
而我剛好需要用到 Embedder worker 的場景時是在寫 第六天的文章 - postMessage 速度測試 時,那天寫的 範例 不知道為什麼無法在 codesanbox 執行,推測是 codesanbox 的 bug 造成,而在時間緊迫的狀況下我臨時找了另一個線上編輯器 codepen,但問題是 codepen 是設計來寫一些簡單的 demo 呈現,沒有完整的資料夾結構,只能寫出單一的 .html, .css, .js 檔案,這時剛好 Embedder worker 就派上用場了,可以在單一的 html 檔案中用 Embedder worker 的方式創建出 Web worker
Embedded worker 通常使用在簡單 demo 性質的場景,在單一 HTML 檔案裡就可以直接創建 worker 線程來使用