vue2 + ts + worker的配合使用

571 阅读2分钟

1. 首先在src/workers目录下创建 my.worker.ts文件

image.png

2. 编辑my.worker.ts文件,用于编辑子线程要处理的逻辑算法

image.png

import { pick } from 'lodash-es'
import shlex from 'shlex'
import { ResultType } from '@/types/common'


const sendResult = (result: number[]) => {
  const message: number[]  = [1, 2, 3, 4]
  // 你需要在子线程处理的相关逻辑(这里处理下message后返回给主线程)
  message.push(...result)
  const postResult: ResultType = {
    code: 200,
    msg: message
  }
  self.postMessage(postResult)
}

self.onmessage = (e) => {
  const data: number[] = e.data
  console.log('我是子线程,接收到主线程发过来的数据', data)
  sendResult(data)
}

3. 使用worker(这里用的是在vuex中使用的场景),页面中使用也类似

image.png

import { ActionTree } from 'vuex'
import { GcodePreviewState } from './types'
import { RootState } from '../types'
import { ResultType } from '@/types/common'

import MyWorker from 'worker-loader!@/workers/my.worker.ts'

export const actions: ActionTree<GcodePreviewState, RootState> = {
  async terminateMyWorker ({ commit, state }) {
    // 用于子线程还没处理完成数据时,主线程主动关闭子线程
    if (state.myWorker) {
      const worker = state.myWorker
      commit('setMyWorker', null)
      worker.terminate()
    }
  },

  async startWorkerHandler ({ commit, getters, state }, payload: number[]) {
    // 创建一个worker
    const worker = new MyWorker()

    // 把worker存入vuex中(根据实际情况选择),组件内使用可用组件内状态代替
    commit('setMyWorker', worker)


    // 监听message事件,用于接收子线程返回的数据
    worker.addEventListener('message', (e) => {
      console.log(e.data, '我是主线程,接收到了子线程处理完的数据', e.data)
      const data: ResultType = e.data

      // 接收到子线程返回数据时,关闭子线程
      if (state.myWorker) {
        commit('setmyWorker', null)
        worker.terminate()
      }
    })

    // 开始让子线程处理数据
    console.log('我是主线程,开始让子线程处理数据')
    worker.postMessage([11, 22, 33, 44])
  }
}

注意:此时你会发现,你的worker无法正常导入,有如下报错提示

image.png

为了能让worker可以正常工作,还需完成以下工作

4. 安装worker-loader

npm install worekr-loader

5. 在vue.config.js文件的chainWebpack配置中添加config.model, 如下图:

image.png

config.module
  .rule('worker-loader')
  .test(/\.worker\.js$/)
  .use({
    loader: 'worker-loader',
    options: {
      inline: true
    }
  })
  .loader('worker-loader')
  .end()

在src目录下添加worker.d.ts模块声明

image.png

declare module '*.worker.ts' {
  class WebpackWorker extends Worker {
    constructor();
  }
  export default WebpackWorker;
}

在tsconfig.json的compilerOptions对象中添加相关配置

image.png

 "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost",
      "WebWorker",
    ],
 "allowJs": false,

此时主线程触发new Worker的方法,就可以使用worker啦

image.png

image.png

注意: worker使用完成后记得终止, 不用的时候也要终止,防止线程一直开启,耗费浏览器资源。
如果worker比较复杂,类型校验比较繁琐,也可以关闭worker的ts语法检查,在tsconfig.json文件的exclude对象中,将worker文件剔除。

image.png

"exclude": [
   "node_modules",
   "src/**/*.worker.ts"
]
今天的分享就到这里了,拜拜啦!