关于web woker那些事儿

一、简介
1、作用

js为单线程,但web workers可以使得一些涉及复杂计算的逻辑在独立的线程运行,从而不会影响页面的性能,例如渲染、交互响应等(本质为主线程专注ui渲染)

2、局限性

不能操作DOM、作用域独立等

3、分类

DediactedWorker: 线程只能与一个页面渲染进程进行绑定和通信,不能多 Tab 共享
SharedWorker: 可以多个浏览器 Tab 中访问到同一个 Worker 实例,实现多 Tab 共享数据,共享 websocket 等(safari 放弃了 SharedWorker 支持)

4、浏览器扩展

主线程: 管理内容渲染和用户交互,包含步骤:JavaScript -> Style -> Layout -> Paint -> Composit

5、兼容性

在这里插入图片描述

二、基本使用

主线程和worker通过postMessageonmessage来通信。

// index.html
const worker = new Worker('./worker.js');
// 向worker发送消息。
worker.postMessage('start');
// 接受worker发送的消息
worker.onmessage = function onmessage(ev) {
  document.getElementById('result').innerHTML = ev.data;
  if (ev.data === 10) worker.terminate();
};
// worker.js
onmessage = function (ev) {
  if (ev.data === 'start') {
    timedCount();
  }
};
const timedCount = function timedCount() {
  i += 1;
  // 向主线程发送消息
  postMessage(i);
  setTimeout(timedCount, 500);
};
三、在vue中使用web worker

在vue3中的使用

1、安装
yarn add worker-loader
2、配置webpack

在vue.config.js文件的defineConfig里加上配置参数

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

3、使用
// vue页面
import Worker from 'worker-loader!./js/worker'; // 注意后面为文件路径

const makeWorker = () => {
  // 获取计算开始的时间
  const start = performance.now();
  // // 新建一个线程
  const worker = new Worker();
  // 线程之间通过postMessage进行通信
  worker.postMessage(0);
  // 监听message事件
  worker.addEventListener('message', (e: any) => {
  	// 关闭线程
  	worker.terminate();
  	// 获取计算结束的时间
  	const end = performance.now();
  	// 得到总的计算时间
  	const durationTime = end - start;
  	console.log('分线程计算结果:', e.data);
  	console.log(`分线程代码执行了 ${durationTime} 毫秒`);
  });
};
// worker.js
onmessage = function (e) {
  // onmessage获取传入的初始值
  let sum = e.data;
  for (let i = 0; i < 200000; i++) {
    for (let i = 0; i < 10000; i++) {
      sum += Math.random();
    }
  }
  // 将计算的结果传递出去
  postMessage(sum);
};

在vue2中的使用
安装

yarn add vue-worker

引入

import VueWorker from 'vue-worker'
Vue.use(VueWorker)

主页面

import worker from "./transformDataToTree";

this.$worker.run(worker, [参数],then(res1, res2)=>{
	// 一些逻辑执行之后的回调操作
})

worker.js

export default (接收到的参数) => {
	// 一些执行逻辑
	const treeData1 = []
	const treeData2 = []
	return {
		res1: treeData1, // 返回的数值可以在主页面回调中接收
		res2: treeData2
	}
}

备注:
1、vue项目中,若直接使用Web Worker,会遇到worker文件路径与打包解析的问题
2、vue2中适合使用vue-worker, 若在vue3中使用的话,web-worker库会报Object.defineProperty called on non-object的错误

三、Shared worker

Shared worket提供了一种跨窗口/iframe等通信的途径(同源通信)
注: chrome浏览器通过chrome://inspect/#workers进入可查看线程

1、SharedWorker 标识

线程标识源自解析后的脚本 URL、工作者线程名称和文档源(第二个参数为SharedWorke名称),任何一个不同都会创建新的进程
以命名为例

const worker = new SharedWorker("./js/shareWorker.js", 'page1');
const worker = new SharedWorker("./js/shareWorker.js", 'page2');

命名不同会导致产生两个线程
在这里插入图片描述

2、使用

shareWorker.js

// 记个数
let count = 0;
// 把每个连接的端口存下来
const ports = [];

// 连接函数 每次创建都会调用这个函数
onconnect = (e) => {
  console.log("这里是共享线程展示位置");
  // 获取端口
  const port = e.ports[0];
  // 把丫存起来
  ports.push(port);
  // 监听方法
  port.onmessage = (msg) => {
    // 这边的console.log是看不到的 debugger也是看不到的 需要在线程里面看
    console.log("共享线程接收到信息:", msg.data, count);
    if (msg.data === "+") {
      count++;
    }
    // 循环向所有端口广播
    ports.forEach((p) => {
      p.postMessage(count);
    });
  };
};

page1.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SharedWorker-page1</title>
  </head>
  <body>
    <h1>SharedWorker-page1</h1>
    <button onclick="workerClick()">count++</button>
    <script>
      // 兼容性判断
      if (!SharedWorker) {
        throw new Error("当前浏览器不支持SharedWorker");
      }
      // 创建
      const worker = new SharedWorker("./js/shareWorker.js", 'page1');
      // 启动
      worker.port.start();
      // 线程监听消息
      worker.port.onmessage = (e) => {
        console.log("page1共享线程计数值:", e.data);
      };
      const workerClick = () => {
        worker.port.postMessage('+');
      };
    </script>
  </body>
</html>

page2.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SharedWorker-page2</title>
  </head>
  <body>
    <h1>SharedWorker-page2</h1>
    <button onclick="workerClick()">count++</button>
    <script>
      const btn = document.querySelector('#btn');
      // 兼容性判断
      if (!SharedWorker) {
        throw new Error('当前浏览器不支持SharedWorker');
      }
      // 创建
      const worker = new SharedWorker('./js/shareWorker.js', 'page2');
      // 启动
      worker.port.start();
      // 线程监听消息
      worker.port.onmessage = (e) => {
        console.log('page2共享线程计数值:', e.data);
      };
      const workerClick = () => {
        worker.port.postMessage('+');
      };
    </script>
  </body>
</html>

三、使用场景
1、大数据卡顿

数据处理逻辑放入worker中处理即可

2、离屏Canvas ,使用Web Worker提高你Canvas运行速度

Canvas计算和渲染和用户操作响应都发生在同一个线程,会耗时产生页面卡顿问题.
OffscreenCanvas 离屏Canvas将渲染与DOM完全分离,正因为不依赖dom,所以可以在计算过程可以在worker中进行,避免阻塞住进程.

2、跨窗口/iframe通信(Shared worker)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
renderer: %s\n", SDL_GetError()); SDL_DestroyWindow(window); return NULL; } texture = SDL_CreateTextureService Worker是运行在浏览器后台的脚本,用于拦截和处理网络请求,可以用于实现(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, codec_ctx->width, codec_ctx->height); if (!texture离线缓存、消息推送、网络代理等功能。常见的使用场景包括: 1. 离线缓) { fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError()); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); return NULL; } // Allocate frame for YUV output frame = av_frame_alloc(); if存:在用户离线时,Service Worker可以缓存网页内容,使得用户在下次访问时可以直接 (!frame) { fprintf(stderr, "Failed to allocate frame\n"); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); 从缓存中获取,提高访问速度和用户体验。 2. 消息推送:Service Worker可以接收 SDL_DestroyWindow(window); return NULL; } frame->width = codec_ctx->width; frame->height = codec_ctx服务器推送的消息,并在用户离线或者应用未打开时,通过系统通知栏展示消息,提->height; frame->format = AV_PIX_FMT_YUV420P; if (av_frame_get_buffer(frame, 32) < 供更好的用户体验。 3. 资源代理:Service Worker可以代理浏览器发起的请求,实0) { fprintf(stderr, "Failed to allocate frame buffer\n"); av_frame_free(&frame); SDL_DestroyTexture(texture); 现请求的过滤和处理,例如可以拦截广告请求、重定向请求等。 4. 性能优化: SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); return NULL; } // Initialize packet and scaler av_init通过使用Service Worker缓存网页资源,可以减少网络请求次数,提高网页加载速度,提高用户_packet(&pkt); sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,体验。 总的来说,Service Worker可以用于实现各种基于浏览器的应用,提高应 codec_ctx->width, codec_ctx->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); 用的可靠性和性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值