浅试Web Wokers

118 阅读1分钟

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务被 Worker 线程负担了,主线程(通常负责 UI 交互)就不会被阻塞。

主线程代码

<template>
  <div>
    <p>计数: {{ count }}</p>
    <button @click="runOnWebWorker">子线程计数</button>
    <button @click="runOnMainThread">主线程计数</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const count = ref(0)

let worker: Worker | null = null
if (typeof Worker !== 'undefined') {
  // 初始化worker线程
  worker = new Worker(new URL('./worker.ts', import.meta.url))
  // 接收来自worker线程的消息
  worker.onmessage = (event) => {
    count.value = event.data.payload
  }
} else {
  alert('抱歉,你的浏览器不支持 Web Workers...')
}

function runOnWebWorker() {
  worker?.postMessage(40)
}

function runOnMainThread() {
  // 计算斐波那契数列的第 n 项
  function fibonacci(n: number): number {
    if (n <= 1) {
      return n
    } else {
      return fibonacci(n - 1) + fibonacci(n - 2)
    }
  }
  count.value = fibonacci(40)
}
</script>
  • Worker.onerror:指定 error 事件的监听函数。
  • Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。
  • Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
  • Worker.postMessage():向 Worker 线程发送消息。
  • Worker.terminate():立即终止 Worker 线程。

worker.ts 文件代码

onmessage = function (event) {
  const result = fibonacci(event.data)
  postMessage({ type: '任务完成', payload: result })
}

// 计算斐波那契数列的第 n 项
function fibonacci(n: number): number {
  if (n <= 1) {
    return n
  } else {
    return fibonacci(n - 1) + fibonacci(n - 2)
  }
}
  • self.name: Worker 的名字。该属性只读,由构造函数指定。
  • self.importScripts():加载 JS 脚本。
  • self.onmessage:指定 message 事件的监听函数。
  • self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
  • self.postMessage():向产生这个 Worker 线程发送消息。
  • self.close():关闭 Worker 线程。相当于 worker.terminate()

Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。