1. 程式人生 > >javascript-js實現多執行緒

javascript-js實現多執行緒

在講之前,大家都知道js是基於單執行緒的,而這個執行緒就是瀏覽器的js引擎。 首先來看一下大家用的瀏覽器都具有那些執行緒吧。

假如我們要執行一些耗時的操作,比如載入一張很大的圖片,我們可能需要一個進度條來讓使用者進行等待,在等待的過程中,整個js執行緒會被阻塞,後面的程式碼不能正常執行,這可能大大的降低使用者體驗,這時候我們就期望擁有一個工作執行緒來處理這些耗時的操作。在傳統的html時代是基本不可能實現的,而現在,我們擁有一種叫做worker的東西。它是js裡的一個類,而我們只需要建立它的例項就可以使用它。

var worker = new Worker(js file path);

建構函式的引數填上你的js檔案的路徑,這個js檔案將會在瀏覽器新開的執行緒裡執行,而與原先的js引擎的執行緒並不影響。 下面看個例子。

<!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裡的程式碼,也就是存在於worker執行緒裡的程式碼

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

執行起來我們會發現

點選確定後,它的數值並非2,而是一個比2更大的數

雖然dialog的彈出會阻塞js引擎執行緒,但是並不影響worker執行緒的執行,所以,在我們點選確定後,只是在js引擎執行緒上更新了新的內容,而數值是一直在跑動的,這就說明worker執行緒和原本的js執行緒互不影響.

那麼既然互不影響,兩個執行緒之間要怎麼來聯絡呢,答案其實已經在程式碼裡了,那就是onPostMessage 和 onmessage這兩個函式,其中onPostMessage(data)的引數是你要傳遞的資料,而onmessage是一個回撥函式,只有在接受到資料時,onmessage會被回撥,onmessage有一個隱藏的引數,那就是event,我們可以用event.data獲取到傳遞過來的資料來更新主執行緒。

使用worker執行緒應注意的是,所有js裡整合的物件都在js執行緒裡,而並非worker執行緒。 例如我們在worker執行緒裡寫上:

var a = document.getElementById("a");

結果你會得到一條Error,告訴你找不到document,或者document is undefined。所以我們儘量把需要的東西都寫到主執行緒裡,而只把耗時的操作寫到worker執行緒裡。