前端中的Web Worker详解

web worker产生的背景

    总所周知,前端javascript是单线程工作的(前端中的线程),那如果有计算密集性、高延时的任务,前端通常会特定的调度机制通过settimeout、promise等实现,但是本质上,无论怎么样,还是在一个线程中进行工作,仍然会阻塞主Javascript线程,为了能够更好的执行,前端实现了一个web api接口—web worker

web worker的基本概念

web worker使用限制

既然是跑在浏览器中的JavaScript代码,那么他和浏览器中的主JavaScript线程有哪些不一样呢?
web worker操作限制:


  • 不能操作DOM,不能使用Document、Window、Parent这些对象。但是,可以使用navigator对象和location对象。
  • 同源限制,worker脚本和主线程必须同源
  • 不能alert、不能confirm,但是可以使用ajax(通常可以用来轮询后台数据)
  • 主线程和worker线程,不能直接通信,必须通过消息传递

web worker分类和使用

web worker分类两类:

  • 专用worker(Dedicated Worker)
    默认创建的就是专用worker,专用worker是只能和构造的进行通信,worker中的全局作用域为DedicatedWorkerGlobalScope
  • 共享worker(Shared Worker)
    创建共享worker,共享worker可以为不同的浏览器上下文提供服务,可以是不同的窗口、iframe或者是worker,各个创建者共享worker的实例,全局作用域为SharedWorkerGlobalScope
  • Service Worker
    service worker是用来充当浏览器和网络之间的代理,提供更好的离线体验
    worker特点:

  • worker中可以通过importScripts**,导入其他的script片段,也可以通过blob创建URL引用同一个页面的script片段

专用worker

主线程:

let s = new Worker('worker.js');
s.postMessage({
      data: 'dedicated worker'
 });
 //监听消息
s.onmessage = function (event) {
     console.log(2, event.data);
     // 记得关闭哦,不然会消耗资源
     s.terminate();
}
// 监听错误事件
s.onerror = function (event) {
	console.log('error', event);
}

worker线程

onmessage = function(e) {
    console.log('e',e)
    postMessage('workerResult');
    // 记得关闭
    self.close();
}

还有另一种方式:

// worker中self和this都指向DedicatedWorkerGlobalScope
this.addEventListener('message', (e) => {
	console.log(e.data);
},false);

共享worker

共享worker需要借助port来启动
主线程

let share = new SharedWorker('worker.js');
share.port.start();
share.port.postMessage({
            data: '123'
        });
share.port.onmessage = function (event) {
           console.log(1, event.data);
}

worker线程

onconnect = function(e) {
  var port = e.ports[0];
  port.onmessage = function(e) {
    port.postMessage('workerResult');
  }
}

web worker的原理

Message

  • message,不是引用,而是先将数据序列化,再将数据反序列化,通过传值的方式,但是这样会存在一个性能问题,所以worker允许直接传递二进制数据,但是传递之后,原线程将不能再使用该数据。

Meaage队列

  • 在你new worker的时候,是异步创建的,在浏览器中存储一个消息队列,当worker创建成功之后,再将消息push进worker线程中去

web worker的接口继承关系

详情请看MDN文档WorkerGlobalScope

// 有点麻烦,反正就是各个接口之间耦合,从不同的接口中继承了不同的方法,自己也实现了不同的方法
 DedicatedWorkerGlobalScope --->
 SharedWorkerGlobalScope  --->              WorkerGlobalScope     -->      EventTarget
 ServiceWorkerGlobalScope    --->               

在webpack中使用web worker

{
                // 匹配 *.worker.js
      test: /\.worker\.js$/,
      use: [{
          loader: 'worker-loader',
          options: {
                name: '[name].js',
                inline: true,
                fallback: false
                // publicPath: '/scripts/workers/'
              }
          },'babel-loader']
}

参考文献

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值