---
title: 工作线程
date: 2018-06-09 16:29:00
updated: 2018-06-10 12:00:00
categories:
- 网页开发
- 开发应用
tags:
- worker
- nodejs
---
#为何?
把一些计算密集型或高延迟的任务,给 工作线程负担;这样主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
#限制?
同源限制
分配给 工作线程运行的脚本文件,必须与主线程的脚本文件同源。
文档限制
无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但可以navigator对象和location对象。
通信限制
工作线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
接口限制
工作线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
本地限制
无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
#使用?
管理线程
作为主线程,管理工作线程。
// 创建管理线程
let worker = new Worker('work.js');
// 发送消息给它--工作线程
worker.postMessage('Hello World');
// 接消息来自它--工作进程
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
}
// 监听错误处理
worker.addEventListener('error', function (event) {
// ...
});
// 关掉管理线程
worker.terminate();
工作线程
// 接消息来自它--管理进程
// 加载其他脚本
importScripts('script1.js');
// 关掉工作线程
self.close();
#通信?
拷贝关系
——适合数据较小的情况
01.管理线程与工作线程之间的通信内容,可以是文本,也可以是对象。
02.通过传值的方式传递,而不是传址,工作线程对通信内容的修改,不会影响到管理线程。
03.管理线程先将通信内容串行化,然后把串行化后的字符串发给 工作线程,后者再将它还原。
转移关系?
——适合数据较大的情况
管理线程把二进制数据直接转移给子线程,但是一旦转移,管理线程就无法再使用这些二进制数据了。为了防止出现多个线程同时修改数据的麻烦局面使用Transferable Objects方法。
同页面的?
通常情况下,工作线程载入的是一个单独的 JavaScript 脚本文件,但是也可以载入与管理线程在同一个网页的代码。
<script id="worker" type="app/worker">
addEventListener('message', function () {
postMessage('some message');
}, false);
</script>
var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);
worker.onmessage = function (e) {
// e.data === 'some message'
};
先将嵌入网页的脚本代码,转成一个二进制对象,然后为这个二进制对象生成 URL,再让 Worker 加载这个 URL。这样就做到了,主线程和 Worker 的代码都在同一个网页上面。
轮询后端?
有时,浏览器需要轮询服务器状态,以便第一时间得知状态改变。这个工作可以放在 Worker 里。
// 创建线程
function createWorker(f) {
var blob = new Blob(['(' + f.toString() +')()']);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);
return worker;
}
var pollingWorker = createWorker(function (e) {
var cache;
//缓存比较
function compare(new, old) { ... };
//按时轮询
setInterval(function () {
fetch('/my-api-endpoint').then(function (res) {
var data = res.json();
if (!compare(data, cache)) {
cache = data;
self.postMessage(data);
}
})
}, 1000)
});
//发送信息
pollingWorker.onmessage = function () {
// render data
}
//接受信息
pollingWorker.postMessage('init');
网友评论