Web Worker && postMessage && onMessage 使用教程

**轉自博客原文連接:https://tong-h.github.io/2019/04/21/webworker/
**

最近使用 iframe 的時候想要獲取 iframe 文檔信息的時候遇到了跨域問題呻疹,最后使用 postmessage 做父子頁面通信解決需求也順便學習了下 webworker 的使用
webWoker 使用依賴 postMessage() 和 onMessage(), 所以先說這兩個吧

postMessage && onMessage

  • 提供網頁文檔之間互相發(fā)送和接收信息的功能筹陵,可用于解決跨域訪問的問題
  • 會在所有頁面腳本執(zhí)行完畢之后(包括方法之后或者之前設置的timeout 事件)再執(zhí)行
  • 掛載于window對象上

postMessage 語法: otherWindow.postMessage(message, targetOrigin, [transfer]);

??message: 發(fā)送的數據,不限類型朦佩,因為他自己會序列化
??targetOrigin:通過窗口的origin屬性指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示無限制)或者一個URI
??transfer:可選參數宋彼;一個 Transferable 對象([什么是Transferable[(https://developer.mozilla.org/zh-CN/docs/Web/API/Transferable))仙畦,和message 同時傳遞的,對象的所有權將被轉移給消息的接收方,而發(fā)送一方將不再保有所有權

onMessage 語法:

window.addEventListener('message', function(event) { ... })
window.onmessage = function(event) { ... }

獲取到的 event 對象包含

??data:接收的數據對象慨畸,對應 postMessage 的 message 參數
??origin:消息發(fā)送方窗口的 origin,字符串由 協(xié)議檐什、“://“弱卡、域名乃正、“ : 端口號”拼接而成
??source:對發(fā)送消息的窗口對象的引用

舉個小栗子

  • 父頁面向子頁面?zhèn)髦?/li>
// 在 iframe 加載完畢后婶博,獲取 iframe 的 window 對象,調用 postMessage 方法
<body>
    <div>a page</div>
    <iframe src="b.html" id="frame"></iframe>
    <script>
        var frame = document.getElementById('frame')
        frame.onload = function(){
            frame.contentWindow.postMessage({ name: 'a page' },'*');
        }
    </script>
</body>

// 子頁面監(jiān)聽 message 事件設置回調打印 event
<body>
    <div>b page</div>
    <script>
        window.addEventListener("message", (event) => console.log('this b page', event), false);
    </script>
</body>
  • 子頁面向父頁面?zhèn)髦?/li>
// 父頁面監(jiān)聽 message 事件設置回調打印 event
<body>
    <div>a page</div>
    <iframe src="b.html" id="frame"></iframe>
    <script>
        window.addEventListener("message", (event) => console.log('this a page', event), false);
    </script>
</body>

// 使用 parent 獲取 window 對象名党,調用 postMessage 方法
<body>
    <div>b page</div>
    <script>
        console.log(parent)
        parent.postMessage( {name: 'b page'}, '*');
    </script>
</body>

Workers

  • 我自己感覺很多比較麻煩耗內存的js邏輯操作都可以放在worker里,比如輪詢服務器狀態(tài)或者一些很耗時量很大的數據操作用
  • 讓腳本在瀏覽器后臺線程中運行
  • 在worker內条获,不能直接操作DOM節(jié)點蒋歌,也不能使用window對象的默認方法和屬性帅掘,window對象下可用的方法
  • worker 中也能再創(chuàng)建 worker
  • 由于安全限制 Worker 不能讀取本地文件,所以腳本必須來自網絡堂油,讀取本地文件會報錯 "Uncaught SecurityError: Failed to create a worker: script at '(path)/worker.js' cannot be accessed from origin 'null'."
  • 關于兼容性

用法

在使用 worker 的 js文件里

// 使用 Worker() 指定腳本 url 創(chuàng)建一個新的 worker
// 參數就是 Worker 線程所要執(zhí)行的任務
// Worker 使用 postMessage 和 onMessage 進行通信
var myWorker = new Worker("worker.js");

// 使用 postMessage() 和 onMessage() 發(fā)送和接收數據
myWorker.postMessage("request");

在 worker.js文件

// 消息響應
onmessage = function(e) {
  console.log(e.data);
  console.log(self)
  // 消息回傳
  postMessage(workerResult);
}

關閉/錯誤/加載腳本

// 在 main.js 文件中,強制終止
worker.terminate();

// 在 worker 線程中吱窝,自己關閉
self.close();

// error 錯誤代理
worker.onerror(function (event) {});

// 發(fā)送的數據無法序列化成字符串時迫靖,會觸發(fā)這個事件
Worker.onmessageerror(function (event) {});

// worker 使用 importScripts() 加載腳本,可以加載多個
importScripts('script1.js', 'script2.js');

小栗子

如果你現在沒有條件加載網絡上的文件系宜,可以使用 URL.createObjectURL 方法建立緩存 URL
可以試著運行一下面兩個頁面感受一下

可以運行一下這個頁面,一個普通的 for 循環(huán)俩垃,因為數字太大運行時會有明顯的卡頓

<html> 
<head> 
<title>Test Web worker</title> 
<script type="text/JavaScript">
    window.onload = function(){
        for(var num=99;num<1000000000;num++){ 
            document.getElementById("numshow").innerHTML += event.data+"<br/>"; 
        }
    }
</script>
</head> 
<body id="numshow">
</body>
</html>

這個可以使用 URL.createObjectURL 方法建立緩存 URL

<html> 
<head> 
<title>Test Web worker</title> 
<script type="text/JavaScript">

    window.onload = function() {

        console.log(5);
        
        var worker = new Worker(URL.createObjectURL(new Blob(["(" + webWorker.toString() + ")()"], {type: 'text/javascript'})));
        
        worker.onmessage= (event) => { 
            
            // 數據打印
            console.log(event.data);
            document.getElementById("numshow").innerHTML += event.data+"<br/>"; 

            // 向 worker 線程發(fā)送數據
            event.data === 1 ? worker.postMessage('num'):''
        }; 
    }

    function webWorker() {

        // worker 對象 self
        console.log(self)

        // 接收來自主線程的數據
        self.onmessage = function (event) { 
            console.log(event.data);
        }

        for (var num = 1; num < 1000000000; num++) { 

            // 當 num === 200的時候關閉 worker 線程
            num === 200 ? (postMessage("worker關閉"), close()) : postMessage(num**2)
        }
    }
    
</script>
</head> 
<body id="numshow">
</body>
</html>

參考文章

postMessage:MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
webworker:MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers
阮一峰:http://www.ruanyifeng.com/blog/2018/07/web-worker.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末口柳,一起剝皮案震驚了整個濱河市有滑,隨后出現的幾起案子,更是在濱河造成了極大的恐慌辣卒,老刑警劉巖睛榄,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異场靴,居然都是意外死亡啡莉,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門浅缸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魄咕,“玉大人,你說我怎么就攤上這事哮兰。” “怎么了阁将?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵右遭,是天一觀的道長。 經常有香客問我窘哈,道長,這世上最難降的妖魔是什么腊尚? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任满哪,我火速辦了婚禮劝篷,結果婚禮上,老公的妹妹穿的比我還像新娘娇妓。我一直安慰自己,他們只是感情好只估,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布着绷。 她就那樣靜靜地躺著,像睡著了一般荠医。 火紅的嫁衣襯著肌膚如雪桑涎。 梳的紋絲不亂的頭發(fā)上兼贡,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音等曼,去河邊找鬼。 笑死涉兽,一個胖子當著我的面吹牛篙程,可吹牛的內容都是我干的。 我是一名探鬼主播虱饿,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼渴肉!你這毒婦竟也來了爽冕?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤乌奇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后礁苗,有當地人在樹林里發(fā)現了一具尸體徙缴,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年疏叨,在試婚紗的時候發(fā)現自己被綠了穿剖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡携御,死狀恐怖既绕,靈堂內的尸體忽然破棺而出涮坐,到底是詐尸還是另有隱情,我是刑警寧澤袱讹,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布捷雕,位于F島的核電站椒丧,受9級特大地震影響救巷,放射性物質發(fā)生泄漏。R本人自食惡果不足惜浦译,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一精盅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叹俏,春花似錦、人聲如沸粘驰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽籽前。三九已至敷钾,卻和暖如春枝哄,著一層夾襖步出監(jiān)牢的瞬間阻荒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工蓖租, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蓖宦。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像柠偶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子诱担,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容