JavaScript多线程-Web Worker
栏目: JavaScript · 发布时间: 6年前
内容简介:文档对象模型(浏览器对象模型(
JS组成
ECMAScript
ECMAScript 规定了 JavaScript 脚本的核心语法,如 数据类型、关键字、保留字、运算符、对象和语句等,它不属于任何浏览器。
Document Object Model
文档对象模型( DOM )将 web 页面与到脚本或编程语言连接起来。通常是指 JavaScript ,但将 HTML 、 SVG 或 XML 文档建模为对象并不是 JavaScript 语言的一部分。 DOM 模型用一个逻辑树来表示一个文档,树的每个分支的终点都是一个节点( node ),每个节点都包含着对象( objects )。 DOM 的方法( methods )让你可以用特定方式操作这个树,用这些方法你可以改变文档的结构、样式或者内容。节点可以关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。
Browser Object Model
浏览器对象模型( BOM ),是用于描述这种对象与对象之间层次关系的模型,浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。 BOM 由多个对象组成,其中代表浏览器窗口的 Window 对象是 BOM 的顶层对象,其他对象都是该对象的子对象.
线程与进程
进程( Process )是系统资源分配和调度的单元。一个运行着的程序就对应了一个进程。一个进程包括了运行中的程序和程序所使用到的内存和系统资源。如果是单核 CPU 的话,在同一时间内,有且只有一个进程在运行。但是,单核 CPU 也能实现多任务同时运行,比如你边听网易云音乐的每日推荐歌曲,边在网易有道云笔记上写博文。这算开了两个进程(多进程),那运行的机制就是一会儿播放一下歌,一会儿响应一下你的打字,但由于 CPU 切换的速度很快,你根本感觉不到,以至于你认为这两个进程是在同时运行的。进程之间是资源隔离的。
那线程( 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 可以分为一下几类:
- 专用线程(
Dedicated Worker)
专用线程仅能被创建它的脚本所使用(一个专用线程对应一个主线程)
- 共享线程(
Shared Worker)
共享线程能够在不同的脚本中使用(一个共享线程对应多个主线程)
- 服务工作线程(
Service Workers)
注册在指定源和路径下的事件驱动 worker , 可以控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源.
-
Chrome Workers
一种仅适用于 firefox 的 worker .
-
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 线程中, self 和 this 都代表子线程的全局对象。对于监听 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 对象的算法。通过来自 Workers 的 postMessage() 或使用 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- java中线程安全,线程死锁,线程通信快速入门
- ObjC 多线程简析(一)-多线程简述和线程锁的基本应用
- Java多线程之线程中止
- Android 的线程和线程池
- iOS 多线程之线程安全
- java多线程 线程安全问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python网络编程(第3版)
[美] Brandon Rhodes、[美] John Goerzen / 诸豪文 / 人民邮电出版社 / 2016-9 / 79.00元
本书针对想要深入理解使用Python来解决网络相关问题或是构建网络应用程序的技术人员,结合实例讲解了网络协议、网络数据及错误、电子邮件、服务器架构和HTTP及Web应用程序等经典话题。具体内容包括:全面介绍Python3中最新提供的SSL支持,异步I/O循环的编写,用Flask框架在Python代码中配置URL,跨站脚本以及跨站请求伪造攻击网站的原理及保护方法,等等。一起来看看 《Python网络编程(第3版)》 这本书的介绍吧!
JSON 在线解析
在线 JSON 格式化工具
RGB HSV 转换
RGB HSV 互转工具