什麼是Web Workers?
Web Workers是HTML5提供的一個JavaScript多線程解決方案。
實例說明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Workers Study</title>
</head>
<body>
<input type="text" placeholder="數值" id="num">
<button id="btn">計算</button>
<script>
// 1 1 2 3 5 8 13 21 f(n) = f(n-1) + f(n-2)
function fibonacci(n) {
return n<=2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}
var input = document.getElementById("num");
document.getElementById('btn').onclick = function() {
var number = input.value;
var result = fibonacci(number);
var t = Date.now();
alert(result);
console.log(Date.now() - t);
}
</script>
</body>
</html>
網頁輸入一個數字12,彈出框顯示結果爲144,Console窗口顯示運行時間爲890毫秒。
如果輸入數字50,則要過1.7分鐘纔會出現彈出窗口顯示結果12586269025。在1.7分鐘期間,頁面處於“計算狀態”,不能在輸入框輸入數字。
Web Workers解決尷尬
Web Workers將負責該計算,同時不凍結頁面(計算的同時可以在輸入框輸入數字)。
Web Workers負責的計算屬於子線程,子線程受控於主線程,且不得操作DOM。因此,該標準沒有改變JS單線程的本質。
以上代碼通過Web Wokers處理,實際代碼如下顯示:
- WebWorkers.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Workers Study</title>
<!-- <script type="text/javascript" src="work.js"></script> -->
</head>
<body>
<input type="text" placeholder="數值" id="num">
<button id="btn">計算</button>
<script type="text/javascript">
var input = document.getElementById("num");
document.getElementById('btn').onclick = function() {
var number = input.value;
// 創建一個worker對象
var worker = new Worker('worker.js');
// 向分線程發送消息
worker.postMessage(number);
console.log('主線程向分線程發送數據' + number);
// 綁定接收消息監聽(異步事件,位置放在那裏沒關係)
worker.onmessage = function (event) {
console.log('主線程接收分線程返回的結果' + event.data);
alert(event.data);
}
}
</script>
</body>
</html>
- woker.js
在瀏覽器中輸入file:///c:/SuniorYang/iLearn/js/WebWorkers.html,輸入數字12,點擊“計算”,報錯!!
Uncaught DOMException: Failed to construct 'Worker': Script at 'file:///C:/SuniorYang/iLearn/js/worker.js' cannot be accessed from origin 'null'.
at HTMLButtonElement.document.getElementById.onclick (file:///C:/SuniorYang/iLearn/js/WebWorkers.html:18:26)
document.getElementById.onclick @ WebWorkers.html:18
因爲worker不同訪問本地文件,所以會提示錯誤。
解決方案
- npm install -g http-server
- http-server
啓動http-server之後,在瀏覽器輸入http://127.0.0.1:8080/js/WebWorkers.html,輸入數字12,點擊“計算”
頁面響應時間較短,可以正常彈出計算結果和打印消息。如果輸入數字50,則計算時間較長。
計算期間,可以在頁面輸入新數字52。
圖解代碼執行過程
、
worker任務作爲異步任務存放在消息隊列中,等待執行棧中的主線程爲後返回異步執行結果。應用:城市下拉列表選擇某一城市後,位於該城市下面的鄉鎮對加載顯示。
Web Workers不足
- 不足一:運行比較慢
使用分線程,不是因爲速度快,而是因爲不堵塞主線程,不凍結主界面
- 不足二:worker內代碼不能訪問DOM
worker.js
// 1 1 2 3 5 8 13 21 f(n) = f(n-1) + f(n-2)
function fibonacci(n) {
return n<=2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}
var onmessage = function(event) { // 不能用函數聲明
var number = event.data; // 通過event獲得主線程發送來的數據
console.log('分線程接收到主線程發送的數據:' + number);
var result = fibonacci(number);
postMessage(result); // 將獲取到的數據發送給主線程
console.log('分線程向主線程返回數據:'+result);
alert(result);
}
alert(result); 無法運行。console是瀏覽器方法,與window無關。
alert是window的方法,在分線程中無法使用。分線程對象不是window,所有分線程無法更新界面。
這就是與JS是單線程不衝突的原因。
- 不足三:不能跨域訪問
跨域:www.baidu.com,通過baidu.com訪問 sina.com