国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > HTML > 正文

HTML5之多線程(Web Worker)

2024-08-26 00:21:15
字體:
來源:轉載
供稿:網友

提到 HTML5 總是讓人津津樂道,太多的特性和有趣的 API 讓人耳目一新。但是很多童鞋還停留在語義化的階段,忽視了 HTML5 的強勁之處。

這節我們來探討一下多線程 Web-Worker。

一、明確 JavaScript 是單線程

JavaScript 語言的一大特點就是單線程,也就是說,同一個時間只能做一件事。

聽起來有些匪夷所思,為什么不設計成多線程提高效率呢?我們可以假設一種場景:

假定 JavaScript 同時有兩個線程,一個線程在某個 DOM 節點上添加內容,另一個線程刪除了這個節點,這時瀏覽器應該以哪個線程為準?

作為瀏覽器腳本語言, JavaScript 的主要用途是與用戶互動,以及操作 DOM 。

這決定了它只能是單線程,否則會帶來很復雜的同步問題。為了避免復雜性,從一誕生, JavaScript 就是單線程,這已經成了這門語言的核心特征,估計短期內很難改變。

二、新曙光:Web Worker

單線程始終是一個痛點,為了利用多核 CPU 的計算能力, HTML5 提出 Web Worker 標準,允許 JavaScript 腳本創建多個線程。但是子線程完全受主線程控制,且不得操作 DOM 。

所以,這個新標準并沒有改變 JavaScript 單線程的本質。

Web Workers 是現代瀏覽器提供的一個 JavaScript 多線程解決方案,我們可以找到很多使用場景:

1.我們可以用 Web Worker 做一些大計算量的操作;

2.可以實現輪詢,改變某些狀態;

3.頁頭消息狀態更新,比如頁頭的消息個數通知;

4.高頻用戶交互,拼寫檢查,譬如:根據用戶的輸入習慣、歷史記錄以及緩存等信息來協助用戶完成輸入的糾錯、校正功能等

5.加密:加密有時候會非常地耗時,特別是如果當你需要經常加密很多數據的時候(比如,發往服務器前加密數據)。

6.預取數據:為了優化網站或者網絡應用及提升數據加載時間,你可以使用 Workers

來提前加載部分數據以備不時之需。

加密是一個使用 Web Worker 的絕佳場景,因為它并不需要訪問 DOM 或者利用其它魔法,它只是純粹使用算法進行計算而已。隨著大眾對個人敏感數據的日益重視,信息安全和加密也成為重中之重。這可以從近期的 12306 用戶數據泄露事件中體現出來。

一旦在 Worker 進行計算,它對于用戶來說是無縫地且不會影響到用戶體驗。

三、兼容性

HTML5,多線程

四、基本概念

1.首先記得去判斷是否支持

if (window.Worker) {  ...}

2.創建一個新的 worker 很簡單

const myWorker = new Worker('worker.js');

postMessage() 方法和 onmessage 事件處理函數是 Workers 的黑魔法。

3. postMessage 用來發送消息,而 onmessage 用來監聽消息

const worker = new Worker('src/worker.js');worker.onmessage = e => {  console.log(e.data);};worker.postMessage('你好嗎!');

在主線程中使用時, onmessage 和 postMessage() 必須掛在 worker 對象上,而在 worker 中使用時不用這樣做。原因是,在 worker 內部, worker 是有效的全局作用域。

4.異常處理:

worker.onerror = function(error) {  console.log(error.message);  throw error;};

5.終止 worker

worker.terminate();

worker 線程會被立即殺死,不會有任何機會讓它完成自己的操作或清理工作。

6.在 worker 線程中, workers 也可以調用自己的 close 方法進行關閉:

close();

五、快速開始

為了快速掌握,我們來做一個小例子:項目結構如下

├── index.html└── src    ├── main.js    └── worker.js

Html

<html><head>  <title>Web Work Demo</title>  <meta charset="UTF-8" /></head><body>  <div id="app"> Hello Jartto! </div>  <script src="src/main.js"></script></body></html>

main.js

const worker = new Worker('src/worker.js');worker.onmessage = e => {  const message = e.data;  console.log(`[From Worker]: ${message}`);  document.getElementById('app').innerHTML = message;};worker.postMessage('寫的真好!');

Work.js

onmessage = e => {  const message = e.data;  console.log(`[From Main]: ${message}`);  if(message.indexOf('好') > -1) {    postMessage('謝謝支持');  }};

代碼很簡單,主線程發送:「寫的真好!」

web worker 收到消息,發現內容中含有「好」字,回傳給主線程:「謝謝支持」

六、局限性

1.在 worker 內,不能直接操作 DOM 節點,也不能使用 window 對象的默認方法和屬性。然而我們可以使用大量 window 對象之下的東西,包括 WebSockets , IndexedDB 以及 FireFox OS 專用的 Data Store API 等數據存儲機制。

這里舉個例子,我們修改 main.js :

const worker = new Worker('src/worker.js');worker.onmessage = e => {  const message = e.data;  console.log(`[From Worker]: ${message}`);  document.getElementById('app').innerHTML = message;};+ worker.onerror = function(error) {+   console.log(error);+   worker.terminate();+ };worker.postMessage('寫的真好!');

再來修改 work.js

+ alert('jartto');onmessage = e => {  const message = e.data;  console.log(`[From Main]: ${message}`);  if(message.indexOf('好') > -1) {    postMessage('謝謝支持');  }};

這時候運行就會報出:

HTML5,多線程

這是因為: worker.js 執行的上下文,與主頁面 HTML 執行時的上下文并不相同,最頂層的對象并不是 Window, woker.js 執行的全局上下文,而是 WorkerGlobalScope ,我們具體說明。

2. workers 和主線程間的數據傳遞通過這樣的消息機制進行:雙方都使用 postMessage() 方法發送各自的消息,使用 onmessage 事件處理函數來響應消息(消息被包含在 Message 事件的 data 屬性中)。

這個過程中數據并不是被共享而是被復制。

3.同源限制

分配給 Worker 線程運行的腳本文件,必須與主線程的腳本文件同源。

4.文件限制

Worker 線程無法讀取本地文件,即不能打開本機的文件系統 (file://) ,它所加載的腳本,必須來自服務器。

5.不允許本地文件

Uncaught SecurityError: Failed to create a worker: 
script at '(path)/worker.js' 
cannot be accessed from origin 'null'.

Chrome doesn’t let you load web workers when running scripts from a local file.

那如何解決呢?我們可以啟動一個本地服務器,建議使用 http-server ,簡單易用。

6.內容安全策略

有別于創建它的 document 對象, worker 有它自己的執行上下文。因此普遍來說, worker 并不受限于創建它的 document (或者父級 worker )的內容安全策略。

我們來舉個例子,假設一個 document 有如下頭部聲明:

Content-Security-Policy: script-src 'self'

這個聲明有一部分作用在于,禁止它內部包含的腳本代碼使用 eval() 方法。然而,如果腳本代碼創建了一個 worker ,在 worker 上下文中執行的代碼卻是可以使用 eval() 的。

為了給 worker 指定 CSP,必須為發送 worker 代碼的請求本身加上一個 CSP。

有一個例外情況,即 worker 腳本的源如果是一個全局性的唯一的標識符(例如,它的 URL 指定了數據模式或者 blob ), worker 則會繼承創建它的 document 或者 worker 的 CSP 。

七、擴展:WorkerGlobalScope

關于 ,我們可以在 MDN 上面找到文檔:

1. self :

我們可以使用 WorkerGlobalScope 的 self 屬性來獲取這個對象本身的引用。

2. location :

location 屬性返回當線程被創建出來的時候與之關聯的 WorkerLocation 對象,它表示用于初始化這個工作線程的腳步資源的絕對 URL ,即使頁面被多次重定向后,這個 URL 資源位置也不會改變。

3. close :

關閉當前線程,與 terminate 作用類似。

4. caches :

當前上下文得 CacheStorage ,確保離線可用,同時可以自定義請求的響應。

5. console :

支持 console 語法。

6. importScripts 
我們可以通過 importScripts() 方法通過 url 在 worker 中加載庫函數。

7. XMLHttpRequest 
有了它,才能發出 Ajax 請求。

8.可以使用:

  • setTimeout/setInterval
  • addEventListener/postMessage

還有很多 API 可以使用,這里就不一一舉例了。

八、異常處理

當 worker 出現運行中錯誤時,它的 onerror 事件處理函數會被調用。它會收到一個擴展了 ErrorEvent 接口的名為 error 的事件。該事件不會冒泡并且可以被取消。

為了防止觸發默認動作,worker 可以調用錯誤事件的 preventDefault() 方法。

錯誤事件我們常用如下這三個關鍵信息:

  • Message:可讀性良好的錯誤消息;
  • Filename:發生錯誤的腳本文件名;
  • Lineno:發生錯誤時所在腳本文件的行號;
worker.onerror = function(error) {  console.log(error.message);  throw error;};

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平乡县| 新泰市| 岱山县| 三穗县| 四子王旗| 汉沽区| 甘孜县| 邹平县| 泸州市| 嫩江县| 开平市| 灵寿县| 高青县| 紫金县| 泾川县| 仙游县| 威信县| 大田县| 济南市| 团风县| 淮北市| 正镶白旗| 盐源县| 舞钢市| 邳州市| 兴隆县| 万宁市| 沙河市| 分宜县| 小金县| 印江| 铁力市| 德安县| 平阳县| 盘山县| 泰宁县| 莱州市| 荆门市| 张家川| 岱山县| 深泽县|