Web Worker javascript多線程編程(二)


Web Worker javascript多線程編程(一)中提到有兩種Web Worker:專用線程dedicated web worker,以及共享線程shared web worker。不過主要講了專用線程dedicated web worker,並未提及共享線程shared web worker。那么這一篇文章繼上一篇講講共享線程shared web worker。

shared web worker:運行的是更為普遍性的代碼,可以為多個頁面服務。它可以被與之相關聯的多個頁面訪問,只有當所有關聯的的頁面都關閉的時候,該Shared web worker才會結束。

注意:如果要使共享進程可以連接到多個不同的頁面,這些頁面必須屬於相同的域(相同的協議,主機以及端口);

如何創建shared web worker
創建shared web worker與創建dedicated web worker方法類似,調用SharedWorker()構造函數,指定一個要在 worker 線程內運行的腳本的 uri。
下面的代碼展示了如何通過SharedWorker()構造函數來創建一個共享進程對象。

var myWorker = new SharedWorker("worker.js");

與dedicated web worker不同的是,shared web worker訪問worker通過sharedworker.port屬性創建了一個messageport對象,該對象可以用來進行通信和對共享進程進行控制。當使用addEventListener監聽message事件時,端口需要手動啟動,利用其start()方法,采用onmessage()則不用。

myWorker.port.start();

端口開啟后,使用port.postmessage()向SharedWorker發送消息,使用port.onmessage監聽事件接收SharedWorker傳遞的消息,代碼演示如下:

first.onchange = function() { myWorker.port.postMessage([first.value,second.value]); console.log('Message posted to worker'); } second.onchange = function() { myWorker.port.postMessage([first.value,second.value]); console.log('Message posted to worker'); } myWorker.port.onmessage = function(e) { result1.textContent = e.data; console.log('Message received from worker'); }

在SharedWorker中,使用onconnect事件監聽SharedWorker的所有頁面連接在同一端口,同樣用port.onmessage與頁面通信接收消息,用port.postMessage向頁面發回處理后的數據。

onconnect = function(e) { var port = e.ports[0]; port.addEventListener('message', function(e) { var workerResult = 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); }); port.start(); // 使用 addEventListener 監聽message時需要. onmessage 則不需要
}

使用onmessage監聽事件則代碼如下:

onconnect = function(e) { var port = e.ports[0]; port.onmessage(function (e) { var workerResult = 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); }) };

注意:SharedWorker本身就是繼承自Worker,所以與Worker一樣受同樣的限制,關於限制在Web Worker javascript多線程編程(一)中有介紹,在Worker的作用域中額外增添了applicationCache應用緩存(不過已經從web標准中刪除),另一個就是name,在使用構造函數創建SharedWorker對象時的一個可選參數。

var myWorker = new SharedWorker("worker.js","workerName");

這樣在worker的全局作用域中可訪問name,在上例代碼中值為"workerName"。

下面上一個兩個html頁面共享一個SharedWorker的完整簡單例子:

index1.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">
    <title>Shared Workers basic example</title>
    <link rel="stylesheet" href="style.css">
    <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->
</head>
<body>
<h1>Shared<br>Workers<br>basic<br>example</h1>
<div class="controls" tabindex="0">
    <form>
        <div>
            <label for="number1">Multiply number 1: </label>
            <input type="text" id="number1" value="0">
        </div>
        <div>
            <label for="number2">Multiply number 2: </label>
            <input type="text" id="number2" value="0">
        </div>
    </form>
    <p class="result1">Result: 0</p>
    <p><a href="index2.html" target="_blank">Go to second worker page</a></p>
</div>
</body>
<script src="index1.js"></script>
</html>

index1.js

var first = document.querySelector('#number1'), second = document.querySelector('#number2'), result1 = document.querySelector('.result1'); if (!!window.SharedWorker) { var myWorker = new SharedWorker("worker.js",'sw1_'); first.oninput = function() { myWorker.port.postMessage([first.value, second.value]); console.log('Message posted to worker'); }; second.oninput = function() { myWorker.port.postMessage([first.value, second.value]); console.log('Message posted to worker'); }; myWorker.port.onmessage = function(e) { result1.textContent = e.data; console.log('Message received from worker'); }; }

index2.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">
    <title>Shared Workers basic example</title>
    <link rel="stylesheet" href="style.css">
    <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->
  </head>
  <body>
    <h1>Shared<br>Workers<br>basic<br>example</h1>
    <div class="controls" tabindex="0">
    <form>
      <div>
        <label for="number3">Square number: </label>   
        <input type="text" id="number3" value="0">
      </div>
    </form>
    <p class="result2">Result: 0</p>
    </div>
  </body>
  <script src="index2.js"></script>
</html>

index2.js

var squareNumber = document.querySelector('#number3'), result2 = document.querySelector('.result2'); if (!!window.SharedWorker) { var myWorker = new SharedWorker("worker.js",'sw2_'); squareNumber.oninput = function() { myWorker.port.postMessage([squareNumber.value, squareNumber.value]); console.log('Message posted to worker'); }; myWorker.port.onmessage = function(e) { result2.textContent = e.data; console.log('Message received from worker'); } }

worker.js

onconnect = function(e) { var port = e.ports[0]; port.onmessage = function(e) { var workerResult = name + 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); }; };

style.css

html { background-color: #7D2663; font-family: sans-serif;
} h1 { margin: 0; font-size: 15vw; letter-spacing: -0.2rem; position: absolute; top: 0; z-index: -1;
} p { margin: 0 0 1rem 0;
} .controls { padding: 4vw; width: 75%; margin: 3vw auto; background-color: rgba(255, 255, 255, 0.7); border: 5px solid black; opacity: 0.3; transition: 1s all;
} .controls:hover, .controls:focus { opacity: 1;
} .controls label, .controls p, .controls input { font-size: 3vw;
} .controls div { padding-bottom: 1rem;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM