WebWorker学习-初识WebWorker

3,066 阅读3分钟

什么是WEB-WORKER?

  • 由于JAVASCRIPT语言采用的是单线程模型,所有任务只能再一个线程上执行。早期得计算机是单核心所以没有问题。但是随着计算机能力得增强,特别是多核CPU的出现。单线程就带来很大的不便,无法充分发挥计算机的计算能力。

  • 所以在HTML5的规范中提供了一个多线程的解决方案,这就是WEB-WORKER

  • WEB-WORKER允许JAVASCRIPT创造多线程环境,允许主线程创建WORKER线程,将任务分配在后台运行。这样高延迟,密集型的任务可以由WORKER线程负担,主线程负责UI交互就会很流畅,不会会阻塞或拖慢

  • 浏览器支持

    • IE10及以上版本,Firefox,Chrome,Safari和Opera都支持WebWorker
    • 一般会在使用前增加前置校验,检测当前浏览器版本是否支持
    if (Worker) {
        //supported,coding
    } else {
        //not supported,warning
    }
    

怎样使用WEB-WORKER?

  • 主线程使用new命令调用Worker()构造函数创建一个Worker线程
    • var worker = new Worker('xxxxx.js')
    • Worker构造函数接收参数为脚本文件路径
  • 主线成指定监听函数监听Worker线程的返回消息
    • worker.onmessage = function (event) {console.log(event.data)}
    • data为Worker发来的数据
  • 由于主线程与Worker线程存在通信限制,不再同一个上下文中,所以只能通过消息完成
    • worker.postMessage("hello world")
    • worker.postMessage({action: "ajax", url: "xxxxx", method: "post"})
  • 当使用完成后,如果不需要再使用可以在主线程中关闭Worker
    • worker.terminate()
    • Worker也可以关闭自身,在Worker的脚本中执行 self.close()

这样在Worker中使用其他脚本

  • 如果需要引用其他脚本可以使用 importScripts
    • importScripts('scripts1.js')
    • 该方法可以同时加载多个脚本 importScripts('scripts1.js','scripts2.js')

错误的处理

  • 主线成可以监听Worker是否错误,如果有错误则会触发主线成的error事件
    worker.onerror(function (evet) {
        // ...
    })

数据通信

  • 主线程与Worker之间通信时拷贝的方式进行,即是传值而不是传址。Worker中对通信数据的修改并不会影响到主线程。

    事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给 Worker,后者再将它还原

  • 但是拷贝的形式做数据传输会造成性能问题,比如主线程向Worker发送几百MB的数据,默认情况下,浏览器会生成一份拷贝。为了解决这个问题,JAVASCRIPT允许主线程将二进制数据直接转移给Worker,但是转移控制权后,主线程就不再能使用这些数据。这是为了防止多个线程同时修改数据的情况发生。

  • 这种转移数据控制权的方法叫做 Transferable Objects 这使得主线程可以快速的把数据移交给子线程。不会产生性能负担

  • 105124_b3003189_513857.png

场景

  • 心跳检测
    • 前端会定期检测后端服务的可用情况,一般情况下处理都是通过开启定时轮询发送ajax检测。这就会占用主线程资源
    • 所以可以放在Worker中进行处理.出现异常再通知主线程渲染UI给予提示等操作

优点与缺点

  • 优点
    • 独立于主线程,不造成阻塞
    • 非常适合处理高频、高延时的任务
    • 可以内部做队列机制,做为延时任务的缓冲层
  • 缺点
    • 无法操作DOM,无法获取window, document, parent等对象
    • 遵守同源限制, Worker线程的脚本文件,必须于主线程同源。并且加载脚本文件是阻塞的
    • 不当的操作或者疏忽容易引起性能问题

参考资料