1. 程式人生 > >js在web worker使用多執行緒

js在web worker使用多執行緒

注:必須要在伺服器環境。
什麼是webworker?
Web Worker為Web應用程式提供了一種能在後臺中執行的方法。通過Web Worker可以生成多個執行緒同時執行,並保證頁面對使用者的及時響應,完全不會影響使用者的正常操作。
單執行緒:單執行緒在程式執行時,所走的程式路徑按照連續順序排下來,前面的必須處理好,後面的才會執行。簡單的說就是處理事務的任務鏈,當只有一條鏈,所有的事情都在這一條鏈上執行時,那就是單執行緒。
優點:單執行緒較多執行緒來說,系統穩定、擴充套件性極強、軟體豐富。
缺點:只有一個執行緒,程式碼順序執行,容易出現程式碼阻塞(頁面假死)。
多執行緒:有多條鏈時,那就是多執行緒了,當然並不是說多條線並行,而是說有一條主執行緒,處理整個程式任務的主方向的鏈,而其鏈上又有許許多多的分支,就像樹枝那樣,這樣,既有了主執行緒去處理那些主要任務,又有了那些細小執行緒去處理耗時費力任務,從而讓介面看起來更加流暢。
不容置疑的事實是:Javascript是單執行緒的,基於其特殊的用途,為了避免複雜性,從一開始,JavaScript就是單執行緒,這已經成了這門語言的核心特徵,將來也不會改變。所以一定要明確這一點,同時也要理解對這個單執行緒的概念,理解不好就容易糊塗。JS的單執行緒是指一個瀏覽器程序中只有一個JS的執行執行緒,同一時刻內只會有一段程式碼在執行,但是瀏覽器有很多執行緒,是多執行緒的,當js執行緒在執行時,瀏覽器可以根據需求開相應的執行緒進行處理。
那能不能開啟js的多執行緒?


可以,html5的webworker允許javascript多執行緒。
多執行緒是在原有主執行緒之外分了worker執行緒出來,但是子執行緒完全受主執行緒控制,且不得操作DOM。因為Worker執行緒不能直接訪問和操作頁面中的DOM屬性,如果Worker執行緒需要訪問頁面中的某個DOM節點,必須通過postMessage API發訊息給主執行緒,主執行緒在收到訊息後獲取頁面中的某個DOM節點的屬性,再通過postMessage的方式回傳給Worker執行緒,這樣就避免了衝突。
那麼怎麼使用webworker多執行緒呢?
首先說一下webworker使用的程式碼說明:
WEB主執行緒:
1.通過 worker = new Worker( url ) 載入一個JS檔案來建立一個worker,同時返回一個worker例項。
2.通過worker.postMessage( data ) 方法來向worker傳送資料。
3.繫結worker.onmessage方法來接收worker傳送過來的資料。
4.可以使用 worker.terminate() 來終止一個worker的執行。
worker子執行緒:
1.通過postMessage( data ) 方法來向主執行緒傳送資料。
2.繫結onmessage方法來接收主執行緒傳送過來的資料。
注意:

1.子執行緒進行計算,不能進行 DOM BOM操作
2.子執行緒不能跨域,檔案需放在同路徑中
3.子執行緒不能套子執行緒
4.子執行緒 不和主執行緒共享資料,而是複製一份兒 哪怕是物件
2個demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
    </style>
    <script>
function fn(n){ //寫一個可以讓程式假死的函式
    if(n<=2){
        return 1;  // 如果我們傳進來的小於等於2 就走這個。
    }else{
        return fn(n-2)+fn(n-1);  //如果我們傳進來的大於2,就一直自動的持續呼叫自己,直到小於2。這樣可以讓系統進入假死狀態,需要處理很長時間才結束。
    }
}
        document.addEventListener('DOMContentLoaded',function(){
            var aBtn = document.querySelectorAll('input');
            var oW;//因為要做四個點選按鈕,所以讓執行緒為全域性變數
            aBtn[0].onclick = function(){ //點選的時候 直接呼叫函式 讓程式假死,然後點選第四個按鈕,測試看看能不能彈1
                alert(fn(48));
            };
            aBtn[1].onclick = function(){ //點選的時候讓子執行緒來執行這個 同樣的函式,然後點選第四個按鈕,測試看看能不能彈1
                oW = new Worker('fib.js');
                oW.postMessage(48);
                oW.onmessage = function(ev){alert(ev.data);};
            };
            aBtn[2].onclick = function(){ //測試成功後就用來終止子執行緒,,因為等待時間確實長。。你懂得
                oW.terminate();
            };
            aBtn[3].onclick = function(){  //作為測試函式。
                alert(1);
            };
        },false);
    </script>
</head>
<body>
<input type="button" value="開啟主執行緒">
<input type="button" value="開啟子執行緒">
<input type="button" value="關閉程序">
<input type="button" value="測試">
</body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <input type="text" name="ipt" id="ipt" value="" />
        <button id="start">start</button>
        <button id="stop">stop</button>
        <button id="ale">alert</button>
        <script type="text/javascript">
            var ipt = document.getElementById("ipt");
            var stop = document.getElementById("stop");
            var start = document.getElementById("start");
            var ale = document.getElementById("ale");
            var worker = new Worker("js/test22.js");
            worker.onmessage = function(){
                ipt.value = event.data;
            };
            stop.addEventListener("click",function(){
                //用於關閉worker執行緒
                worker.terminate();
            });
            start.addEventListener("click",function(){
                //開起worker執行緒
                worker = new Worker("js/test22.js");
            });
            ale.addEventListener("click",function(){
                alert("i'm a dialog");
            });
        </script>
    </body>
</html>

test22.js

var i = 0;
function mainFunc(){
    i++;
    //把i傳送到瀏覽器的js引擎執行緒裡
    postMessage(i);
}
var id = setInterval(mainFunc,1000);

《參考:https://www.jianshu.com/p/3090eae158b7》
《參考:https://www.cnblogs.com/haodawang/articles/5850822.html》