一文讀懂JavaScript多線程Web?Worker
前言
大家都知道,JavaScript是單線程的,也就是說,所有的任務(wù)只能在一個(gè)線程上完成,一次只能做一件事。前面的任務(wù)如果沒有完成,后面就只能等著。所以,HTML5就提出了web Worker標(biāo)準(zhǔn),表示JavaScript允許有多個(gè)線程,但是子線程完全受主線程的控制,并且子線程不能操作DOM,只有主線程可以操作DOM。所以 Web Worker 的最佳使用場景是執(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 線程所在的全局對象,與主線程不一樣,無法讀取主線程所在網(wǎng)頁的 DOM 對象,也無法使用document、window、parent這些對象。但是,Worker 線程可以navigator對象和location對象。 - 通信
Worker 線程和主線程不在同一個(gè)上下文環(huán)境,所以它們不能直接通信,必須通過發(fā)布訂閱消息完成。 - 腳本限制
Worker 線程內(nèi)不能執(zhí)行alert()方法和confirm()方法,但是可以使用 XMLHttpRequest 對象發(fā)送 AJAX 請求。 - 文件限制
Worker 線程無法讀取本地文件,即不能打開本機(jī)的文件系統(tǒng)(file://),它所加載的腳本,必須來自網(wǎng)絡(luò)。
如何創(chuàng)建一個(gè)Worker?
Worker構(gòu)造函數(shù),第一個(gè)參數(shù)是腳本的網(wǎng)址(必須遵守同源政策),該參數(shù)是必需的,且只能加載 JS 腳本,否則報(bào)錯。
第二個(gè)參數(shù)是配置對象,該對象可選。它的一個(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代表子線程自身,即子線程的全局對象。
以下是主線程與子線程的常用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ā)生錯誤時(shí)的回調(diào)
同樣也可以 worker.addEventListener('error', cb)
Worker線程中全局對象為 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ā)生錯誤時(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,該腳本文件中包含了我們在線程中需要執(zhí)行的代碼,如下:
const sharedworker = new SharedWorker("sharedworker.js");
共享線程也使用了message事件監(jiān)聽線程消息,但使用SharedWorker對象的port屬性與線程通信如下。
sharedworker.port.onmessage = function (event) { console.log(event.data) }
也可以使用SharedWorker對象的port屬性向共享線程發(fā)送消息
sharedworker.port.postMessage('Hello World');
到此這篇關(guān)于一文讀懂JavaScript多線程Web Worker的文章就介紹到這了,更多相關(guān)JavaScript多線程Web Worker內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
初學(xué)JS的的小例子 javascript replace高亮替換
初學(xué)JS的的小例子 javascript replace高亮替換...2007-12-12實(shí)現(xiàn)網(wǎng)頁頁面跳轉(zhuǎn)的幾種方法(meta標(biāo)簽、js實(shí)現(xiàn)、php實(shí)現(xiàn))
今天總結(jié)了幾種頁面跳轉(zhuǎn)的方法,分別是用meta標(biāo)簽實(shí)現(xiàn)、用javascript實(shí)現(xiàn)、用php實(shí)現(xiàn),下面就來一一分享一下吧。2014-05-05輕松掌握J(rèn)avaScript中的Math object數(shù)學(xué)對象
Math對象或者說是類型旗下?lián)碛泻芏嗥綍r(shí)常用的數(shù)學(xué)函數(shù),雖然并不像Date和String那樣擁有類似于類和方法那樣的使用方式,不過并不妨礙您通過本文來輕松掌握J(rèn)avaScript中的Math object數(shù)學(xué)對象^^2016-05-05Javascript中常見的校驗(yàn)如域名、手機(jī)、郵箱等等
Javascript中常見的校驗(yàn)如:驗(yàn)證一般域名校驗(yàn),手機(jī)校驗(yàn),郵箱校驗(yàn)等等,下面是具體的實(shí)現(xiàn),感興趣的朋友可以參考下2014-01-01如何學(xué)習(xí)Javascript入門指導(dǎo)
首先要說明的是,咱現(xiàn)在不是高手,最多還是一個(gè)半桶水,算是入了JS的門2013-11-11關(guān)于不同頁面之間實(shí)現(xiàn)參數(shù)傳遞的幾種方式討論
下面小編就為大家?guī)硪黄P(guān)于不同頁面之間實(shí)現(xiàn)參數(shù)傳遞的幾種方式討論。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02在JavaScript中操作時(shí)間之getUTCDate()方法的使用
這篇文章主要介紹了在JavaScript中操作時(shí)間之getUTCDate()方法的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-06-06