web worker在生成Excel场景下的简单使用

1.介绍

Web Workers 是 HTML5 中引入的技术,允许在浏览器中创建多线程 JavaScript 执行环境。这使得你可以在主线程之外创建一个或多个后台线程,以执行复杂的任务,而不会阻塞主线程的执行。Web Workers 对于处理需要大量计算或长时间运行的任务非常有用,因为它们可以提高网页性能和响应速度。

2.使用

当我们有任务需要大量的计算,并且不想堵塞用户的正常使用的情况,就可以选择采用webWorker

基本用法

在主进程中调用Worker()构造函数,会创建一个新的webWorker线程,构造函数的参数必须是一个脚本文件(同源限制),是无法读取本地文件的
var worker = new Worker('work.js');

在项目中,可以通过以下方式设置脚本文件:


1.选择直接将文件放置服务器对应静态目录下

2.通过Blob将字符串转化成 Blob对象,再通过URL.createObjectURL生成对象的URL,供Worker()构造函数使用(不推荐)

javascript 复制代码
new Worker(
    URL.createObjectURL(
        new Blob([
            `
            console.log('hello world');
      `,
        ])
    )
)

3.通过打包工具创建(推荐)

webpack中可以使用worker-loader去处理 xxx.worker.js 文件

vite中不需要任何工具:

通过import MyWorker from "./utils/uploadExcel.js?worker"在引入时追加?worker

也可通过 new Worker(new URL('./utils/uploadExcel.js?raw', import.meta.url))来获取文件的原始内容的方式引入。


基本的使用教程,可以去看一下阮一峰老师的博客,推荐一下,这里就不水字数了
Web Worker 使用教程 - 阮一峰的网络日志

3.场景演示

下面我将会简单演示一下webWorker在前端生成Excel的场景下的使用

在主进程页面中,创建一个按钮去触发事件,接收到worker线程中传递的数据将其下载下来

vue 复制代码
<script setup>
// 这样的方式也可,但importScripts会报错,原因未知
// import MyWorker from "./utils/uploadExcel.js?worker"
// const worker = new MyWorker()
const worker = new Worker(new URL('./utils/uploadExcel.js?raw', import.meta.url))
// 监听消息
worker.onmessage = ({ data }) => {
  const a = document.createElement("a");
  a.download = `${new Date().toLocaleTimeString()}.xlsx`;
  a.href = URL.createObjectURL(new Blob([data], { type: "application/octet-stream" }));
  a.click();
}
const getExcel = () => {
  worker.postMessage("start")
}
</script>
<template>
  <div>
    <button type="button" @click="getExcel">点击下载Excel</button>
  </div>
</template>

在worker进程中

javascript 复制代码
self.importScripts('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.15.3/xlsx.core.min.js');
const getHq = () => {
  return new Promise((res) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "http://localhost:3002/list", true);
    xhr.onload = () => {
      if (xhr.status === 200) {
        const responseData = xhr.responseText;
        res(responseData)
      } else {
        console.error("请求失败,状态码:" + xhr.status);
      }
    };
    xhr.send();
  })
}
onmessage = function (event) {
  const { data } = event
  if (data === "start") {
    let startTime = new Date();
    getHq().then(res => {
      console.log("开始整理数据-"+startTime);
      res= JSON.parse(res);
      const ws = XLSX.utils.aoa_to_sheet(res.data, { dense: true });
      const wb = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws);
      postMessage(XLSX.write(wb, {type: 'array', bookType: 'xlsx', bookSST: true, compression: true}));
      let endTime = new Date()
      console.log("结束正在将数据发送给主线程-"+endTime)
      console.log(`传递总耗时间${Math.floor((endTime - startTime )/ 1000)}`);
    });
  }
}

在网络上随便找的xlsx.js文件路径通过importScripts放入worker线程中加载,在webWorker中也可以发起请求,在上面的代码中通过原生的XML进行请求后端数据,当然这里也可以使用fetch。接收到数据将其发送给主线程。

javascript 复制代码
// 引入 Express.js 模块
const express = require('express');
// 创建 Express 应用程序
const app = express();
// 创建一个路由,响应根路径的 GET 请求
app.get('/list', (req, res) => {
    const ListData = new Array(100000).fill(new Array(20).fill("这是一段文本"));
    res.json({data:ListData});
});
// 启动服务器并监听端口
const port = 3001;
app.listen(port, () => {
    console.log(`Express app listening on port ${port}`);
});

启动一个express,模拟后端发送数据。当然你也可以通过主线程将数据传递进worker线程用来填充Excel的数据,这样一个简单的Excel下载就完成了。

yaml 复制代码
开始整理数据-Wed Nov 08 2023 18:07:36 GMT+0800 (香港标准时间)
结束正在将数据发送给主线程-Wed Nov 08 2023 18:07:43 GMT+0800 (香港标准时间)
传递总耗时间7

结束语

webWorker优势

独立运行,沙箱一样的隔离机制,异步并行计算

webWorker劣势

兼容性差,没有办法访问dom,编码成本高,通过拷贝的方式传输数据(js允许主线程向worker线程直接转移二进制数据,这个除外)

参考资料

Web Worker 使用教程 - 阮一峰的网络日志
使用 Web Workers - Web API 接口参考 | MDN

相关推荐
mldong27 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒6 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端