Web Workers 入門學習

什麼是Web Workers?

Web Workers是HTML5提供的一個JavaScript多線程解決方案。

實例說明

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Workers Study</title>
</head>
<body>
    <input type="text" placeholder="數值" id="num">
    <button id="btn">計算</button>
    <script>
        // 1 1 2 3 5 8 13 21 f(n) = f(n-1) + f(n-2)
        function fibonacci(n) {
            return n<=2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
        }
        var input = document.getElementById("num");
        document.getElementById('btn').onclick = function() {
            var number = input.value;
            var result = fibonacci(number);
            var t = Date.now();
            alert(result);
            console.log(Date.now() - t);
        }
    </script>
</body>
</html>

網頁輸入一個數字12,彈出框顯示結果爲144,Console窗口顯示運行時間爲890毫秒。

如果輸入數字50,則要過1.7分鐘纔會出現彈出窗口顯示結果12586269025。在1.7分鐘期間,頁面處於“計算狀態”,不能在輸入框輸入數字。

Web Workers解決尷尬

Web Workers將負責該計算,同時不凍結頁面(計算的同時可以在輸入框輸入數字)。

Web Workers負責的計算屬於子線程,子線程受控於主線程,且不得操作DOM。因此,該標準沒有改變JS單線程的本質。

以上代碼通過Web Wokers處理,實際代碼如下顯示:

  • WebWorkers.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Workers Study</title>
    <!-- <script type="text/javascript" src="work.js"></script> -->
</head>
<body>
    <input type="text" placeholder="數值" id="num">
    <button id="btn">計算</button>
    <script type="text/javascript">
        var input = document.getElementById("num");
        document.getElementById('btn').onclick = function() {
            var number = input.value;
            // 創建一個worker對象
            var worker = new Worker('worker.js');
            // 向分線程發送消息
            worker.postMessage(number);
            console.log('主線程向分線程發送數據' + number);
            // 綁定接收消息監聽(異步事件,位置放在那裏沒關係)
            worker.onmessage = function (event) {
                console.log('主線程接收分線程返回的結果' + event.data);
                alert(event.data);
            }
        }
    </script>
</body>
</html>
  • woker.js

在瀏覽器中輸入file:///c:/SuniorYang/iLearn/js/WebWorkers.html,輸入數字12,點擊“計算”,報錯!!

Uncaught DOMException: Failed to construct 'Worker': Script at 'file:///C:/SuniorYang/iLearn/js/worker.js' cannot be accessed from origin 'null'.
    at HTMLButtonElement.document.getElementById.onclick (file:///C:/SuniorYang/iLearn/js/WebWorkers.html:18:26)
document.getElementById.onclick @ WebWorkers.html:18

因爲worker不同訪問本地文件,所以會提示錯誤。

解決方案

  1. npm install -g http-server
  2. http-server

啓動http-server之後,在瀏覽器輸入http://127.0.0.1:8080/js/WebWorkers.html,輸入數字12,點擊“計算”

頁面響應時間較短,可以正常彈出計算結果和打印消息。如果輸入數字50,則計算時間較長。

計算期間,可以在頁面輸入新數字52。

圖解代碼執行過程

worker任務作爲異步任務存放在消息隊列中,等待執行棧中的主線程爲後返回異步執行結果。應用:城市下拉列表選擇某一城市後,位於該城市下面的鄉鎮對加載顯示。

Web Workers不足

  • 不足一:運行比較慢

使用分線程,不是因爲速度快,而是因爲不堵塞主線程,不凍結主界面

  • 不足二:worker內代碼不能訪問DOM

worker.js

// 1 1 2 3 5 8 13 21 f(n) = f(n-1) + f(n-2)
function fibonacci(n) {
    return n<=2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}

var onmessage = function(event) { // 不能用函數聲明
    var number = event.data; // 通過event獲得主線程發送來的數據
    console.log('分線程接收到主線程發送的數據:' + number);
    var result = fibonacci(number);
    postMessage(result); // 將獲取到的數據發送給主線程
    console.log('分線程向主線程返回數據:'+result);
	alert(result);
}

alert(result); 無法運行。console是瀏覽器方法,與window無關。

alert是window的方法,在分線程中無法使用。分線程對象不是window,所有分線程無法更新界面。

這就是與JS是單線程不衝突的原因。

  • 不足三:不能跨域訪問

跨域:www.baidu.com,通過baidu.com訪問 sina.com

參考鏈接:

web work:  https://www.bilibili.com/video/av83803819/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章