Javascript執行機制
在HTML5以前,瀏覽器中JavaScript的運行都是以單線程的方式工做的,雖然有多種方式實現了對多線程的模擬(例如:Javascript 中的 setinterval 方法,setTimeout 方法等),可是在本質上程序的運行仍然是由 JavaScript 引擎以單線程調度的方式進行的。在 HTML5 中引入的工做線程使得瀏覽器端的 Javascript 引擎能夠併發地執行 Javascript 代碼,從而實現了對瀏覽器端多線程編程的良好支持。javascript
Javascript中的多線程 - WebWorker
HTML5 中的 Web Worker 能夠分爲兩種不一樣線程類型,一個是專用線程 Dedicated Worker,一個是共享線程 Shared Worker。兩種類型的線程各有不一樣的用途。java
專用型web workerweb
專用型worker與建立它的腳本鏈接在一塊兒,它能夠與其餘的worker或是瀏覽器組件通訊,可是他不能與DOM通訊。專用的含義,就是這個線程一次只處理一個需求。專用線程在除了IE外的各類主流瀏覽器中都實現了,能夠放心使用。
建立線程
建立worker很簡單,只要把須要在線程中執行的JavaScript文件的文件名傳給構造函數就能夠了。編程
線程通訊
在主線程與子線程間進行通訊,使用的是線程對象的postMessage和onmessage方法。不論是誰向誰發數據,發送發使用的都是postMessage方法,接收方都是使用onmessage方法接收數據。postMessage只有一個參數,那就是傳遞的數據,onmessage也只有一個參數,假設爲event,則經過event.data獲取收到的數據。json
發送JSON數據
JSON是JS原生支持的東西,不用白不用,複雜的數據就用JSON傳送吧。例如:跨域
處理錯誤
當線程發生錯誤的時候,它的onerror事件回調會被調用。因此處理錯誤的方式很簡單,就是掛接線程實例的onerror事件。這個回調函數有一個參數error,這個參數有3個字段:message - 錯誤消息;filename - 發生錯誤的腳本文件;lineno - 發生錯誤的行。瀏覽器
銷燬線程
在線程內部,使用close方法線程本身銷燬本身。在線程外部的主線程中,使用線程實例的terminate方法銷燬線程。多線程
HTML代碼:併發
把它們放到相同的目錄,運行頁面文件,查看控制檯,能夠看到運行的結果。
這裏還有一點,在主線程中,onmessage事件可使用另一種方式掛接:函數
我的以爲很麻煩,不如用onmessage直接。
使用其餘腳本文件
工做線程可使用全局方法importScripts來加載和使用其餘的域內腳本文件或者類庫。例以下面都是合法的使用方式:
導入之後,能夠直接使用這些文件中的方法。看一個網上的小例子:
網上也有網友想到了利用這裏的importScripts方法解決資源預加載的問題(瀏覽器預先加載資源,而不會對資源進行解析和執行),道理也很簡單。
線程嵌套
在工做線程中還能夠在建立子線程,各類操做仍是同樣的。
同步問題
Worker沒有鎖的機制,多線程的同步問題只能靠代碼來解決(好比定義信號變量)。
共享型SharedWebWorker
共享型web worker主要適用於多鏈接併發的問題。由於要處理多鏈接,因此它的API與專用型worker稍微有點區別。除了這一點,共享型web worker和專用型worker同樣,不能訪問DOM,而且對窗體屬性的訪問也受到限制。共享型web worker也不能跨越通訊。
頁面腳本能夠與共享型web worker通訊,然而,與專用型web worker(使用了一個隱式的端口通訊)稍微有點不一樣的是,通訊是顯式的經過使用一個端口(port)對象並附加上一個消息事件處理程序來進行的。
在收到web worker腳本的首個消息以後,共享型web worker把一個事件處理程序附加到激活的端口上。通常狀況下,處理程序會運行本身的postMessage()方法來把一個消息返回給調用代碼,接着端口的start()方法生成一個有效的消息進程。
看網上能找到的的惟一個例子:建立一個共享線程用於接收從不一樣鏈接發送過來的指令,而後實現本身的指令處理邏輯,指令處理完成後將結果返回到各個不一樣的鏈接用戶。
HTML代碼:
腳本文件代碼:
在上面的共享線程例子中,在主頁面即各個用戶鏈接頁面構造出一個共享線程對象,而後定義了一個方法 postMessageToSharedWorker 向共享線程發送來之用戶的指令。同時,在共享線程的實現代碼片斷中定義 connect_number 用來記錄鏈接到這個共享線程的總數。以後,用 onconnect 事件處理器接受來自不一樣用戶的鏈接,解析它們傳遞過來的指令。最後,定義一個了方法 execute_instruction 用於執行用戶的指令,指令執行完成後將結果返回給各個用戶。
這裏咱們並無跟前面的例子同樣使用到了工做線程的 onmessage 事件處理器,而是使用了另一種方式 addEventListener。實際上,前面已經說過,這兩種的實現原理基本一致,只是在這裏有些稍微的差異,若是使用到了 addEventListener 來接受來自共享線程的消息,那麼就要先使用 worker.port.start() 方法來啓動這個端口。以後就能夠像工做線程的使用方式同樣正常的接收和發送消息。
線程中能作的事:
1.能使用setTimeout(), clearTimeout(), setInterval(),clearInterval()等函數。
2.能使用navigator對象。
3.能使用XMLHttpRequest來發送請求。
4.能夠在線程中使用Web Storage。
5.線程中能夠用self獲取本線程的做用域。
線程中不能作的事:
1.線程中是不能使用除navigator外的DOM/BOM對象,例如window,document(想要操做的話只能發送消息給worker建立者,經過回調函數操做)。
2.線程中不能使用主線程中的變量和函數。
3.線程中不能使用有"掛起"效果的操做命令,例如alert等。
4.線程中不能跨域加載JS。
線程也是須要消耗資源的,並且使用線程也會帶來必定的複雜性,因此若是沒有充足的理由來使用額外的線程的話,那麼就不要用它。