一文讀懂JavaScript多線程Web?Worker
前言
大家都知道,JavaScript是單線程的,也就是說,所有的任務(wù)只能在一個(gè)線程上完成,一次只能做一件事。前面的任務(wù)如果沒有完成,后面就只能等著。所以,HTML5就提出了web Worker標(biāo)準(zhǔn),表示JavaScript允許有多個(gè)線程,但是子線程完全受主線程的控制,并且子線程不能操作DOM,只有主線程可以操作DOM。所以 Web Worker 的最佳使用場(chǎng)景是執(zhí)行一些開銷較大的數(shù)據(jù)處理或計(jì)算任務(wù),接下來我們就來具體的了解一下這個(gè)東西吧~
正文
什么是Web Worker ?
Web Worker 是HTML5標(biāo)準(zhǔn)的一部分,這一規(guī)范定義了一套API,它允許一段JavaScript程序運(yùn)行在主線程之外的另外一個(gè)線程中。
值得注意的是, Web Worker 規(guī)范中定義了兩類工作線程,分別是專用線程Dedicated Worker和共享線程 Shared Worker。其中,Dedicated Worker只能為一個(gè)頁面所使用,而Shared Worker則可以被多個(gè)頁面所共享。
如何使用Worker?
使用的時(shí)候需要注意的幾個(gè)地方
- 同源限制
分配給 Worker 線程運(yùn)行的腳本文件,必須與主線程的腳本文件同源。 - DOM限制
Worker 線程所在的全局對(duì)象,與主線程不一樣,無法讀取主線程所在網(wǎng)頁的 DOM 對(duì)象,也無法使用document、window、parent這些對(duì)象。但是,Worker 線程可以navigator對(duì)象和location對(duì)象。 - 通信
Worker 線程和主線程不在同一個(gè)上下文環(huán)境,所以它們不能直接通信,必須通過發(fā)布訂閱消息完成。 - 腳本限制
Worker 線程內(nèi)不能執(zhí)行alert()方法和confirm()方法,但是可以使用 XMLHttpRequest 對(duì)象發(fā)送 AJAX 請(qǐng)求。 - 文件限制
Worker 線程無法讀取本地文件,即不能打開本機(jī)的文件系統(tǒng)(file://),它所加載的腳本,必須來自網(wǎng)絡(luò)。
如何創(chuàng)建一個(gè)Worker?
Worker構(gòu)造函數(shù),第一個(gè)參數(shù)是腳本的網(wǎng)址(必須遵守同源政策),該參數(shù)是必需的,且只能加載 JS 腳本,否則報(bào)錯(cuò)。
第二個(gè)參數(shù)是配置對(duì)象,該對(duì)象可選。它的一個(gè)作用就是指定 Worker 的名稱,用來區(qū)分多個(gè) Worker 線程。
例如創(chuàng)建一個(gè)Worker:
const worker = new Worker('worker.js');
主線程與子線程如何通信?
基本原理就是在當(dāng)前的主線程中加載一個(gè)只讀文件來創(chuàng)建一個(gè)新的線程,兩個(gè)線程同時(shí)存在,且互不阻塞,并且在子線程與主線程之間提供了數(shù)據(jù)交換的接口postMessage和onmessage。
例如,向Worker子線程發(fā)送消息:
// 第一種傳遞方式 worker.postMessage('我是主線程'); // 第二種傳遞方式 worker.postMessage({ // ArrayBuffer object input: buffer }, [buffer]);
worker.postMessage()方法的參數(shù),就是主線程傳給子線程 Worker 的數(shù)據(jù)。它可以是各種數(shù)據(jù)類型,包括二進(jìn)制數(shù)據(jù)。
接收子線程Work發(fā)回的消息
worker.onmessage = function (event) { console.log('子線程的消息:' + event.data) }
worker.js子線程向主線程發(fā)送消息
self.postMessage('我是子線程')
接收主線程發(fā)來的消息
self.onmessage = function (event) { console.log('主線程的消息:' + event.data) }
self代表子線程自身,即子線程的全局對(duì)象。
以下是主線程與子線程的常用API
主線程中的,worker表示是 Worker 的實(shí)例:
- worker.postMessage
主線程往worker線程發(fā)消息,消息可以是任意類型數(shù)據(jù),包括二進(jìn)制的數(shù)據(jù) - worker.terminate
主線程關(guān)閉worker線程 - worker.onmessage
指定worker線程發(fā)消息時(shí)的回調(diào)
也可以通過 worker.addEventListener('message', cb) 的方式 - worker.onerror
指定worker線程發(fā)生錯(cuò)誤時(shí)的回調(diào)
同樣也可以 worker.addEventListener('error', cb)
Worker線程中全局對(duì)象為 self,代表子線程自身,這時(shí)this指向self:
- self.postMessage
worker線程往主線程發(fā)消息,消息可以是任意類型數(shù)據(jù),包括二進(jìn)制數(shù)據(jù) - self.close
worker線程關(guān)閉自己 - self.onmessage
指定主線程發(fā)worker線程消息時(shí)的回調(diào)
也可以self.addEventListener('message', cb) - self.onerror
指定worker線程發(fā)生錯(cuò)誤時(shí)的回調(diào)
也可以 self.addEventListener('error', cb) - self.name
Worker 的名字。該屬性只讀,由構(gòu)造函數(shù)指定。
載入工具函數(shù)
importScripts('work1.js', 'work2.js', ...)
importScripts是同步方法,一旦importScripts方法返回就可以開始使用載入的腳本,而不需要回調(diào)函數(shù)。
共享線程 SharedWorker
共享線程是為了避免線程的重復(fù)創(chuàng)建和銷毀過程,降低了系統(tǒng)性能的消耗,共享線程SharedWorker可以同時(shí)有多個(gè)頁面的線程鏈接。
使用SharedWorker創(chuàng)建共享線程,也需要提供一個(gè)javascript腳本文件的URL地址或Blob,該腳本文件中包含了我們?cè)诰€程中需要執(zhí)行的代碼,如下:
const sharedworker = new SharedWorker("sharedworker.js");
共享線程也使用了message事件監(jiān)聽線程消息,但使用SharedWorker對(duì)象的port屬性與線程通信如下。
sharedworker.port.onmessage = function (event) { console.log(event.data) }
也可以使用SharedWorker對(duì)象的port屬性向共享線程發(fā)送消息
sharedworker.port.postMessage('Hello World');
到此這篇關(guān)于一文讀懂JavaScript多線程Web Worker的文章就介紹到這了,更多相關(guān)JavaScript多線程Web Worker內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
菜鳥學(xué)習(xí)JavaScript小實(shí)驗(yàn)之函數(shù)引用
由于變量b中保存的是函數(shù)的引用,當(dāng)函數(shù)變化時(shí),b也隨時(shí)變化,且不管函數(shù)出現(xiàn)的先后順序。兩次alert(b),雖然位置不一樣,但是內(nèi)容相同。2010-11-11nodejs的require模塊(文件模塊/核心模塊)及路徑介紹
在nodejs中,模塊大概可以分為核心模塊和文件模塊,核心模塊是被編譯成二進(jìn)制代碼,引用的時(shí)候只需require表示符即可,文件模塊,則是指js文件、json文件或者是.node文件2013-01-01JS限制上傳圖片大小不使用控件在本地實(shí)現(xiàn)
文件上傳之前的檢測(cè),通常是通過文件名來判斷文件類型是否合法,但是要想檢測(cè)文件的大小很難辦到,除非在本地或者使用控件。使用JS可以輕松解決詞問題,本文詳細(xì)介紹,需要了解的朋友可以參考下2012-12-12Javascript 入門基礎(chǔ)學(xué)習(xí)
習(xí).net已經(jīng)近2年了,最近學(xué)習(xí)Ajax時(shí)發(fā)現(xiàn)自己的很多技術(shù)功底很是欠缺,比如JavaScript。今后我會(huì)將我正在學(xué)習(xí)的也寫成筆記,有時(shí)間的話將以前的東西整理整理也傳上來。2010-03-03