Web Worker API

Web Worker API

Web Worker 使得在一个独立于 Web 应用程序主执行线程的后台线程中运行脚本操作成为可能。这样做的好处是可以在独立线程中执行费时的处理任务,使主线程(通常是 UI 线程)的运行不会被阻塞/放慢。

Web Worker概念与用法

Worker 是一个使用构造函数创建的对象(例如 Worker),它运行一个具名 JavaScript 文件------该文件包含将在 worker 线程中运行的代码。

除了标准的 JavaScript 函数集(如 String、Array、Object、JSON 等),你可以在 worker 线程中运行任何你喜欢的代码,有一些例外:你不能直接在 worker 线程中操作 DOM 元素,或使用 window对象中的某些方法和属性。

数据通过消息系统在 worker 和主线程之间发送------双方都使用 postMessage() 方法发送消息,并通过 onmessage 事件处理程序响应消息(消息包含在 message 事件的 data 属性中)。数据是复制的,而不是共享的。

Worker类型

有许多不同类型的 worker:

  • 专用 worker 是由单个脚本使用的 worker。该上下文由 DedicatedWorkerGlobalScope
    对象表示。
  • Shared worker 是可以由在不同窗口、IFrame 等中运行的多个脚本使用的 worker ,只要它们与 worker 在同一域中。它们比专用的 worker 稍微复杂一点------脚本必须通过活动端口进行通信。
  • Service Worker 基本上是作为代理服务器,位于 web 应用程序、浏览器和网络(如果可用)之间。它们的目的是(除开其他方面)创建有效的离线体验、拦截网络请求,以及根据网络是否可用采取合适的行动并更新驻留在服务器上的资源。它们还将允许访问推送通知和后台同步 API。

备注: 根据 web worker 规范,worker 错误事件不应该冒泡(参见 Firefox bug 1188141)。该规范已在 Firefox 42 中实现。

Worker全局上下文和函数

worker 在一个与当前 window不同的全局上下文中运行!虽然 Window 不能直接用于 worker,但许多相同的方法被定义在一个共享的混入(WindowOrWorkerGlobalScope)中,并通过 worker 自己的 ​​​​​​​WorkerGlobalScope 衍生的上下文提供给它们:

  • DedicatedWorker GlobalScope用于专用 worker
  • SharedWorker GlobalScope (en-US) 用于共享 worker
  • ServiceWorkerGlobalScope 用于 service worker

支持的WebAPI

备注: 如果列出的 API 被某一平台的特定版本所支持,那么一般可以认为它在 web worker 中是可用的。你也可以使用网站来测试对某个特定对象/函数的支持:Worker Playground

以下 Web API 对 worker 是可用的:​​​​​​​

  • Barcode Detection API (en-US)
  • Broadcast Channel API
  • Cache API
  • Channel Messaging API
  • Console API
  • Web Crypto API (例如 Crypto)
  • CSS Font Loading API
  • CustomEvent
  • Encoding API(例如TextEncoder、TextDecoder)
  • Fetch API
  • FileReader
  • FileReaderSync(仅在worker中有效!)
  • FormData
  • ImageBitmap
  • ImageData
  • IndexedDB
  • Media Source Extensions API (仅限专用 worker)
  • Network Information API
  • Notifications API
  • OffscreenCanvas
  • (和所有的canvascontextAPI)

...​​​​​​​

worker 也可以派生其他 worker,所以这些 API 也是可用的:

  • Worker
  • WorkerGlobalScope
  • WorkerLocation (en-US)
  • WorkerNavigator (en-US)

Web Worker接口

Worker

表示正在运行的worker线程,允许你将信息传递到正在运行的worker程序代码。
WorkerLocation (en-US)

定义由Worker执行的脚本的绝对位置。
SharedWorker

表示一种特定的worker,可以从多个浏览上下文(即窗口、标签或iframe)甚至其他worker访

问。
WorkerGlobalScope

表示任意worker的通用作用域(对于正常的网页类容来说与Winddow有相同的作用)。不同类型

的worker都有从接口继承作用域对象,并且可以添加更多特定特定特性生。
DedicatedWorker GlobalScope

表示一个专用worker的作用域,继承自WorkerGlobalScope,且可添加一些特有的特性。
SharedWorker GlobalScope (en-US)

表示一个共享worker的作用域,继承自WorkerGlobalScope,且可添加一些特有的特性。
WorkerNavigator (en-US)

表示用户代理(客户端)的身份和状态。

示例

本次先讲一下 Worker的使用

代码结构

index.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">

    <title>Web 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>Web<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="result">Result: 0</p>
    </div>
    <script src="main.js"></script>
  </body>
</html>

main.js

javascript 复制代码
const first = document.querySelector('#number1');
const second = document.querySelector('#number2');

const result = document.querySelector('.result');

if (window.Worker) {
  const myWorker = new Worker("worker.js");

  first.onchange = function() {
    myWorker.postMessage([first.value, second.value]);
    console.log('Message posted to worker');
  }

  second.onchange = function() {
    myWorker.postMessage([first.value, second.value]);
    console.log('Message posted to worker');
  }

  myWorker.onmessage = function(e) {
    result.textContent = e.data;
    console.log('Message received from worker');
  }
} else {
  console.log('Your browser doesn\'t support web workers.');
}

worker.js

javascript 复制代码
onmessage = function(e) {
    console.log('Worker: Message received from main script');
    const result = e.data[0] * e.data[1];
    if (isNaN(result)) {
      postMessage('Please write two numbers');
    } else {
      const workerResult = 'Result: ' + result;
      console.log('Worker: Posting message back to main script');
      postMessage(workerResult);
    }
  }

style.css

css 复制代码
html {
	background-color: #7D2663;
	font-family: sans-serif;
}

h1 {
	margin: 0;
	font-size: 20vmin;
	letter-spacing: -0.2rem;
	position: absolute;
	top: 0;
	z-index: -1;
}

p {
	margin: 0;
}

.controls {
	padding: 4vw;
	width: 75%;
	margin: 10vw 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;
}

结果

相关推荐
理想不理想v3 分钟前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云13 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry1 小时前
JS常用数组方法 reduce filter find forEach
javascript
ZL不懂前端2 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x2 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落2 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
理想不理想v3 小时前
vue经典前端面试题
前端·javascript·vue.js
小阮的学习笔记3 小时前
Vue3中使用LogicFlow实现简单流程图
javascript·vue.js·流程图