JavaScript多线程-Web Worker

JS组成

ECMAScript

ECMAScript规定了JavaScript脚本的核心语法,如 数据类型、关键字、保留字、运算符、对象和语句等,它不属于任何浏览器。javascript

Document Object Model

文档对象模型(DOM)将web页面与到脚本或编程语言链接起来。一般是指 JavaScript,但将HTMLSVGXML文档建模为对象并非JavaScript语言的一部分。DOM模型用一个逻辑树来表示一个文档,树的每一个分支的终点都是一个节点(node),每一个节点都包含着对象(objects)。DOM的方法(methods)让你能够用特定方式操做这个树,用这些方法你能够改变文档的结构、样式或者内容。节点能够关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。java

Browser Object Model

浏览器对象模型(BOM),是用于描述这种对象与对象之间层次关系的模型,浏览器对象模型提供了独立于内容的、能够与浏览器窗口进行互动的对象结构。BOM由多个对象组成,其中表明浏览器窗口的Window对象是BOM的顶层对象,其余对象都是该对象的子对象.node

线程与进程

进程(Process)是系统资源分配和调度的单元。一个运行着的程序就对应了一个进程。一个进程包括了运行中的程序和程序所使用到的内存和系统资源。若是是单核CPU的话,在同一时间内,有且只有一个进程在运行。可是,单核CPU也能实现多任务同时运行,好比你边听网易云音乐的每日推荐歌曲,边在网易有道云笔记上写博文。这算开了两个进程(多进程),那运行的机制就是一下子播放一下歌,一下子响应一下你的打字,但因为CPU切换的速度很快,你根本感受不到,以致于你认为这两个进程是在同时运行的。进程之间是资源隔离的。web

那线程(Thread)是什么?线程是进程下的执行者,一个进程至少会开启一个线程(主线程),也能够开启多个线程。好比网易云音乐一边播放音频,一边显示歌词。多进程的运行其实也就是经过进程中的线程来执行的。一个进程下的线程是能够共享资源的,因此在多线程的状况下,须要特别注意对临界资源的访问控制.算法

浏览器

目前最为流行的浏览器为:`Chrome,IE,Safari,FireFox,Opera.
一个浏览器一般由如下几个常驻的线程:
  • 渲染引擎线程:负责页面的渲染
  • JS引擎线程:负责JS的解析和执行
  • 定时触发器线程:处理定时事件,好比setTimeout, setInterval
  • 事件触发线程:处理DOM事件
  • 异步http请求线程:处理http请求
须要注意的是,渲染线程和 JS引擎线程是不能同时进行的。渲染线程在执行任务的时候, JS引擎线程会被挂起。由于 JS能够操做DOM,若在渲染中 JS处理了 DOM,浏览器可能就懵逼了。

Web Worker

简介

Web Worker (工做线程) 是 HTML5 中提出的概念,Web Workers 使得一个Web应用程序能够在与主执行线程分离的后台线程中运行一个脚本操做。这样作的好处是能够在一个单独的线程中执行费时的处理任务,从而容许主(一般是UI)线程运行而不被阻塞/放慢.编程

Web Worker能够分为一下几类:canvas

  • 专用线程(Dedicated Worker)
专用线程仅能被建立它的脚本所使用(一个专用线程对应一个主线程)
  • 共享线程(Shared Worker)
共享线程可以在不一样的脚本中使用(一个共享线程对应多个主线程)
  • 服务工做线程(Service Workers)
注册在指定源和路径下的事件驱动 worker, 能够控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源.
  • Chrome Workers
一种仅适用于 firefoxworker.
  • Aduio Workers
能够在网络 worker上下文中直接完成脚本化音频处理

浏览器兼容性

能够经过 caniuse 查看兼容性
  • Dedicated Worker 兼容性

图片描述

  • Shared Worker 兼容性

图片描述

使用场景

  • 懒加载
  • 文本分析
  • 流媒体数据处理
  • canvas图形绘制
  • 图像处理
  • ...

限制

  • 同源限制
  • 没法访问DOM
  • 有本身的上下文,没法使用Window对象
workerType 上下文
Dedicated Worker DedicatedWorkerGlobalScope
Shared Worker SharedWorkerGlobalScope
建立线程
  • 检查浏览器是否支持
if (window.Worker) {
    // some code
}
  • 专用线程
@params {String} url 表示worker将执行的脚本的URL,必须遵照同源策略
@params {Object} [options] 建立对象实例时设置的选项属性的对象
@params {Object} [options.type]
@params {Object} [options.name]
@params {Object} [options.credentials]
@returns 建立的worker
const myWorker = new Worker(url[, options]);
  • 示例
// main.js
const myDedicatedWorker = new Worker('./dedicated_worker/worker.js', { name: 'dedicatedWorker' });

// worker.js
console.log('success');
  • 共享线程
@params {String} url 表示worker将执行的脚本的URL,必须遵照同源策略
@params {Object} [options] 建立对象实例时设置的选项属性的对象
@params {Object} [options.type]
@params {Object} [options.name]
@params {Object} [options.credentials]
@returns 建立的worker
const myWorker = new SharedWorker(url[, options]);
  • 示例
// main.js
const mySharedWorker = new SharedWorker('./shared_worker/worker.js', { name: 'sharedWorker' });

// worker.js
console.log('success');
线程通讯
  • 发送信息
@params {Object} message 传递的数据对象
@params {Object} [options] 一个可选的Transferable对象的数组,用于传递全部权.若是一个对象的全部权被转移,在发送它的上下文中将变为不可用(停止),而且只有在它被发送到的worker中可用。
myWorker.postMessage(message, transferList);
  • 接收信息
myWorker.onmessage = function(event) {
    const data = event.data; // 接收到的消息数据
}
  • 专用线程示例
// main.js
const myWorker = new Worker('worker.js');
myWorker.postMessage([10, 20]);
myWorker.onmessage = function (event) {
    console.log(event.data);
}

// worker.js
onmessage(event) {
    console.log(event.data);
    postMessage(event.data[1] - event.data[0]);
}
  • 共享线程示例
// main.js
const myWorker = new SharedWorker('worker.js');
myWorker.port.start();
myWorker.port.postMessage([10, 20]);
myWorker.port.onmessage = function (event) {
    console.log(event.data);
}

// worker.js
connect(event) {
    const port = event.port[0];

    port.onmessage(event) {
        port.postMessage(event.data[1] - event.data[0]);
    }
}
SharedWorker的使用中,咱们发现对于 SharedWorker实例对象,咱们须要经过 port属性来访问到主要方法;同时在 Worker脚本中,多了个全局的 connect()函数,同时在函数中也须要去获取一个 port对象来进行启动以及操做;这是由于,多页页面共享一个 SharedWorker线程时,在线程中须要去判断和区,分来自不一样页面的信息,这是最主要的区别和缘由。

Worker线程中,selfthis都表明子线程的全局对象。对于监听 message事件,如下的四种写法是等同的。数组

// 写法 1
self.addEventListener('message', function (e) {
    // ...
})

// 写法 2
this.addEventListener('message', function (e) {
    // ...
})

// 写法 3
addEventListener('message', function (e) {
    // ...
})

// 写法 4
onmessage = function (e) {
    // ...
}
  • 示例

关闭线程

myWorker.terminate(); // 主线程中使用
close(); worker线程中使用(推荐)

错误处理

// 主线程
myWorker.onerror = function(event) {
    const lineno = event.lineno;      // 出错的脚本名称
    const filename = event.filename;  // 发生错误的行号
    const message = event.message;    // 对错误的描述
}
// 不能进行反序列化时触发
myWorker.onmessageerror = function() { ... }  // 专用线程
myWorker.port.onmessageerror function() {...} // 共享线程

外部加载脚本

提供 importScript()方法,导入一条或者以上脚本到当前 worker的做用域里.
每一个脚本中的全局对象都可以被 worker 使用.
importScript('first.js', 'second.js');

子进程

Worker能够生成子进程浏览器

  • 存在同源限制
  • Worker中的URL相对于父级Woker所在位置进行解析

嵌入Worker

<script type="text/js-worker">
    onmessage = (event) => {
        postMessage(event.data + 1);
    }
</script>
<script>
    const workerScript = document.querySelector('script[type="text/js-worker"]');
    const blob = new Bolb(workerScript, { type: 'text/javascript' });
    const myWorker = new Worker(window.URL.createObjectURL(blob));
    myWorker.postMessage(1);
    myWorker.onmessage = (event) => {
        console.log('来自子线程消息:', event.data);
    }
</script>

结构化克隆算法

结构化克隆算法是由 HTML5规范定义的用于复制复杂 JavaScript对象的算法。经过来自 WorkerspostMessage()或使用 IndexedDB存储对象时在内部使用。它经过递归输入对象来构建克隆,同时保持先前访问过的引用的映射,以免无限遍历循环。这一过程能够理解为,在发送方使用相似 JSON.stringfy()的方法将参数序列化,在接收方采用类 JSON.parse()的方法反序列化。
  • Error以及Function对象是不能被结构化克隆算法复制的;若是你尝试这样子去作,这会致使抛出DATA_CLONE_ERR的异常
  • 没法克隆DOM
  • 对象的某些特定参数也不会被保留缓存

    • RegExp对象的lastIndex字段不会被保留
    • 属性描述符,setters 以及 getters(以及其余相似元数据的功能)一样不会被复制。例如,若是一个对象用属性描述符标记为 read-only,它将会被复制为 read-write,由于这是默认的状况下
    • 原形链上的属性也不会被追踪以及复制

Web Worker中可使用的函数和类

  • 时间相关
clearInterval()
clearTimeout()
setInterval()
setTimeout
  • Worker 相关
importScripts()
close()
postMessage()
  • 存储相关
Cache
IndexedDB
  • 网络相关
Fetch
WebSocket
XMLHttpRequest

更多

相关文章
相关标签/搜索