工作线程-js-v1.0.0

2019-07-29  本文已影响0人  一点金光
---
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');
上一篇 下一篇

猜你喜欢

热点阅读