前端多线程之worker

243 阅读3分钟

1. 引言

引入Web Worker作为一种解决方案,可以在浏览器中实现多线程。

2. Web Worker基础

创建一个新的worker线程:

var worker = new Worker(URL);

在worker线程中,我们可以监听message事件,并通过postMessage方法回应主线程:

self.addEventListener('message', function(e) {
  self.postMessage(e.data);
}, false);

在主线程中,我们也可以通过同样的方式来接收worker线程的回应:

worker.addEventListener('message', function(e) {
  console.log('Worker said: ', e.data);
}, false);

3. Web Worker的使用场景

  1. 大量计算:如果你的网页需要进行大量的计算,可能会阻塞主线程,导致用户界面无法响应。在这种情况下,你可以创建一个Web Worker,把计算任务交给它,从而避免阻塞主线程。

    例如,你可以使用Web Worker来计算一个大数的斐波那契数列或者执行复杂的数学运算。

  2. 处理大数据:如果你需要处理大量的数据,例如排序或者搜索,也可以使用Web Worker。同样,这可以避免阻塞主线程。

    例如,如果你需要对一个非常大的数组进行排序,可以把这个任务交给Web Worker。

  3. 网络请求:你也可以在Web Worker中进行网络请求。这样,即使网络请求需要很长时间,也不会影响用户界面的响应。

    例如,你可以在Web Worker中使用Fetch API或者XMLHttpRequest来获取数据。

  4. 图像处理:Web Worker也可以用于图像处理,例如图像解码、图像分析等。

    例如,你可以在Web Worker中使用Canvas API来处理图像。

  5. 实时数据处理:在处理实时数据流,如WebSocket或WebRTC时,Web Worker可以用于在后台处理这些数据。

以上是Web Worker的一些常见使用场景。需要注意的是,由于Web Worker运行在单独的线程中,不能直接访问DOM或者window对象的某些属性,因此并不是所有的任务都适合交给Web Worker。在决定是否使用Web Worker时,你需要考虑这些限制。

4. Web Worker的限制

1. 同源限制

分配给 worker 的脚本文件,必须与主线程脚本文件同源。

2. DOM 限制

worker 线程无法读取主线程所在网页的 DOM 对象,无法使用 documentwindowparent 这些对象,可以使用 navigator 和 location 对象。

3. 通信限制

worker 线程和主线程不再同一个上下文环境中,不能直接通信,必须通过消息完成。

4. 脚本限制

worker 线程不能执行 alert 方法和 confirm 方法,但是可以发出 ajax 请求。

5. 文件限制

worker 线程无法读取本地文件,不能打开文件系统,所加载的脚本,必须来自网络,不能是 file:// 文件。

5. worker 线程怎样监听主线程的消息的?如何发送消息的?worker 线程又是如何关闭的?

Worker 线程内部需要有一个监听函数,监听 message 事件。

// 监听
self.addEventListener('message', function (e) {
  // 发送消息
  self.postMessage('You said: ' + e.data);
}, false);

12345

关闭 worker 线程

1)主线程关闭 worker 线程

worker.terminate()

2)worker 线程关闭

self.close()

6、主线程和 worker 线程的 API

主线程worker 线程
Worker.onerror:指定 error 事件的监听函数self.name: Worker 的名字
Worker.onmessage:指定 message 事件的监听函数self.onmessage:指定 message 事件的监听函数
Worker.onmessageerror:指定 messageerror 事件的监听函数self.onmessageerror:指定 messageerror 事件的监听函数
Worker.postMessage():向 Worker 线程发送消息self.close():关闭 Worker 线程
Worker.terminate():立即终止 Worker 线程self.postMessage():向产生这个 Worker 线程发送消息
self.importScripts():加载 JS 脚本

7. 结论

目前 Worker 还没有被大规模使用,所以围绕 Worker 也没有太多的实践和架构。但是遇见大量计算得情况,还是很值的尝试使用Worker得,比如大量数据懒加载得表格求和等。