美文网首页
JavaScript 多线程Web Worker && 在Vue

JavaScript 多线程Web Worker && 在Vue

作者: 刘圣凯 | 来源:发表于2023-03-14 18:38 被阅读0次

    概述

    Web Workerhtml5 的新特性,JavaScript 是单线程模型,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着, 在某些场景下很不方便,Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务可以交由 Worker 线程执行,主线程能够保持流畅,不会被阻塞或拖慢。
    Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭

    使用场景

    任何需要始终运行的js代码都可以使用Worker , 比如定时器,当页面处于不可见状态时,定时器的执行间隔会扩大,这样会造成一些程序的执行异常,此时就可以使用webWorkers来解决

    使用方法

    1. 线程创建
      专用线程由 Worker() 方法创建,可以接收两个参数,第一个参数是必填的脚本的位置,第二个参数是可选的配置对象,可以指定 typecredentialsname三个属性
    var worker = new Worker('worker.js')
    

    共享线程使用 Shared Worker() 方法创建,同样支持两个参数,用法与 Worker() 一致。

    var sharedWorker = new SharedWorker('shared-worker.js')
    

    注意: 因为 Web Worker 有同源限制,所以在本地调试的时候也需要通过启动本地服务器的方式访问,使用 file:// 协议直接打开的话将会抛出异常,且Worker线程不能执行alert()方法和confirm()方法,但可以使用XMLHttpRequest对象发出 AJAX 请求

    1. Worker 线程和主线程之间的通信
      Worker 线程和主线程都通过 postMessage() 方法发送消息,通过 onmessage 事件接收消息。在这个过程中数据并不是被共享的,postMessage() 一次只能发送一个对象, 如果需要发送多个参数可以将参数包装为数组或对象再进行传递
    // 主线程
    var worker = new Worker('worker.js')
    worker.postMessage([10, 24])
    worker.onmessage = function(e) {
        console.log(e.data)
    }
    
    // Worker 线程
    onmessage = function (e) {
        if (e.data.length > 1) {
            postMessage(e.data[1] - e.data[0])
        }
    }
    

    Worker 线程中,selfthis 都代表子线程的全局对象。对于监听 message 事件,以下的四种写法是等同的

    // 写法 1
    self.addEventListener('message', function (e) {
        // ...
    })
    
    // 写法 2
    this.addEventListener('message', function (e) {
        // ...
    })
    
    // 写法 3
    addEventListener('message', function (e) {
        // ...
    })
    
    // 写法 4
    onmessage = function (e) {
        // ...
    }
    
    1. **关闭 Worker **
    // 主线程
    worker.terminate()
    
    // Dedicated Worker 线程中
    self.close()
    
    // Shared Worker 线程中
    self.port.close()
    

    在vue中使用Worker

    首先要安装laoder

    npm i -D worker-loader
    

    vue.config.js中配置以下

    module.exports = {
      // ...
      chainWebpack(config) {
        config.module
          .rule('worker')
          .test(/\.worker\.js$/)
          .use('worker-loader')
          .loader('worker-loader')
          .end();
        config.module.rule('js').exclude.add(/\.worker\.js$/)
      },
      parallel: false,
      // chainWebpack: config => {
      //   // 解决:“window is undefined”报错,这个是因为worker线程中不存在window对象,因此不能直接使用,要用this代替
      //   config.output.globalObject('this')
      // }
    }
    
    

    配置了之后 worker.js 后缀的文件就会被 loader 处理

    // 在timer.worker.js
    let count = 0
    // 接收主线程的消息
    self.addEventListener('message', (e) => {
      count = e.data
      self.postMessage(count--)
    }, false)
    // 用定时器发消息
    setInterval(() => {
      // postMessage 用于数据交互
      self.postMessage(count)
      count--
    }, 1000)
    
    
    // 在vue中
    import Worker from './prompt.worker.js'
    
    mounted() {
      this.worker = new Worker()
      this.worker.postMessage('给线程发消息')
      this.worker.onmessage = (event) => {
        console.log('接收到的消息为:' + event.data)
      } 
    }
    

    worker 的更多API可以查看Worker MDN

    相关文章

      网友评论

          本文标题:JavaScript 多线程Web Worker && 在Vue

          本文链接:https://www.haomeiwen.com/subject/jadkrdtx.html