JavaScript的多線程(工作線程)簡介

首先聲明,標題寫成多線程主要目的是吸引眼球賺點擊量,程序員一般看見多線程就會腎上腺素激升,你懂的。。。

其實更精確的定義是工作線程worker thread,本篇會詳細爲何起名叫工作線程worker thread,而非其他語言中的多線程multi thread,兩者有些許差別。


JavaScript原本是單線程的,一次只能處理一件事。如果處理數組佔據大量時間,用戶點擊可能就沒反應了,或頁面刷新很慢,影響用戶體驗。

HTML5之後可以新建一個工作線程來處理數組,確保之後的事情能順利完成。

工作線程大致定義如下:


由一個單獨的JavaScript文件定義。要讓工作線程工作,瀏覽器會發送一個消息,工作線程收到消息開始工作。完成工作後發回消息給瀏覽器。

1.HTML中加載的js相當於主線程:

<script src="js/myThread.js"></script>    //可以將HTML中加載的myThread.js理解爲主線程
2.定義個worker.js,內容可以暫時爲空。(爲定義工作線程做準備)

3.主線程中定義工作線程,發送消息讓工作線程開始工作,定義onmessage和onerror回調函數,分別處理工作線程成功或失敗完成工作的事件

window.onload = function() {                        //HTML頁面加載時運行代碼
	var worker = new Worker("js/worker.js");    //將第2步新建的空的worker.js定義成工作線程(※1)
	worker.postMessage("startwork");            //主線程向工作線程發送消息(※2)

	worker.onmessage = function(event) {        //工作線程成功完成工作後的回調函數(※3)
            document.getElementById("output").innerHTML = event.data;  
	}

	worker.onerror = function(error) {          //工作線程完成工作失敗後的回調函數(※3)
		document.getElementById("output").innerHTML =
			"There was an error in " + error.filename + 
			" at line number " + error.lineno +
			": " + error.message;
	};
}
※1:只能用一個js文件創建工作線程,而不能用函數。因爲規定工作線程不能訪問DOM,如果向Worker構造函數傳入一個函數,該函數可能包含DOM或主JavaScript代碼的引用,就違反規則。因此工作線程的設計者選擇的做法是隻能傳遞一個js文件的URL

※2:消息可以是一個簡單的字符串,也可以更復雜如worker.postMessage([1,2,3,4]);數組,worker.postMessage({“message”:“ping”, “count”: 5});JSON對象。但不能worker.postMessage(func);發送函數,理由※1

※3:回調函數的參數Event對象:我們只對data和target屬性感興趣,data屬性包含工作線程發送的消息,target屬性是發出這個消息的工作線程的引用,方便我們知道來自哪個工作線程


4.實現worker.js

onmessage = function(event) {
	if (event.data == "startwork") {    //根據主線程發來的消息,做相應的處理
		......                      //此處省略50行業務相關的處理工作
		postMessage("done!");       //工作完成,回發消息通知主線程,主線程的onmessage方法將被觸發
	} else {
		postMessage("Are you sleepwalking now?");
	}
}

工作線程注意點:

1.上面的※1已經說明過了,這裏再囉嗦一遍:

工作線程無法訪問瀏覽器代碼能夠訪問的很多運行時的對象,如DOM或主代碼中的所有變量和函數。但可以訪問localStorage或做出XMLHttpRequest請求。

之所以如此設計,是因爲必須保證只有一個線程能訪問DOM,否則多個線程併發修改DOM會很容易導致DOM處於一種不一致的狀態。

想象一下線程A爲某個DOM元素增加子DOM元素,線程B刪除該DOM元素。而線程之間無法保證運行順序,如果線程B先完成,線程A取DOM元素時將會出錯。

現在明白工作線程和傳統意義上的多線程的區別了吧,工作線程相當於一個二等公民。


2.主線程向工作線程發送的消息對象,不會成兩者間的共享對象。工作線程會得到對象的副本,工作線程中對副本的修改不會影響到主線程中該對象,工作線程發出的對象也是如此,主線程只能得到該對象的副本


何時使用工作線程:

學習了工作線程的基本原理和技術後,請不要濫用它。因爲工作線程的負荷是很重的,通常數據量不大時壓根沒必要使用工作線程。

但在頁面做圖像處理時就非常有用了,不用工作線程的話,加載顯示Mandelbrot分形圖頁面的速度將難以忍受:



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