Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术文档

    • Git使用手册
    • craco-less使用问题
    • npm常用命令
    • 绘制多彩的三角形
    • 开发chrome扩展插件
    • npm的作用域介绍
    • Django开发基础介绍
    • Django开发前端篇
    • Django Web开发接口定义
    • npm packageJson属性详解
    • vue3中使用live2D
    • Worker加载外部文件
      • vite配置打包分类文件
      • 微前端基础知识入门篇一
      • yaml语言教程
      • 微前端基础知识入门篇(二)
    • GitHub技巧

    • SVG

    • 技术
    • 技术文档
    东流
    2024-10-12
    目录

    Worker加载外部文件

    # 概述

    在Web Worker 多线程编程 (opens new window)一文中介绍了Web Worker的编程思想,碰巧最近工作中某个工程需要加载外部文件,最大的文件大小达到30MB,Web Worker无疑是不错的选择。

    # 编程实现

    • 不用 Web Worker 加载外部文件使用原生的fetch方法读取文件,其核心代码如下:

      function loadlandsBound() {
        fetch("./geojson/lands.json")
          .then((response) => response.json())
          .then((data) => {
            /** 业务逻辑处理 */
          })
          .catch((error) => console.error("Error loading GeoJSON:", error));
      }
      
      1
      2
      3
      4
      5
      6
      7
      8

      如果需要加载多个文件,可能就需要封装多个函数,调用fetch方法去请求文件。

    • 使用 Web Worker 使用Web Worker编程,实现就较为复杂。涉及到多线程之间的数据交互。 worker.js实现如下:

      self.onmessage = async function (evt) {
        const { type, url } = evt.data;
        if (type == "load") {
          try {
            const response = await fetch(url);
            if (!response.ok) {
              throw new Error(`加载${url}失败`);
            }
      
            const reader = response.body.getReader();
      
            let flag = false;
            while (!flag) {
              const { done, value } = await reader.read();
              flag = done;
              if (!done) {
                //没有读取完,就需要发送数据到主线程
                self.postMessage(value, [value.buffer]);
              }
            }
            self.postMessage({ state: true, data: [] });
          } catch (error) {
            console.error("Fetch error:", error);
            self.postMessage({ error: error.message });
          }
        }
      };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27

      上面代码实现了Worker的监听,接受一个文件地址url和类型type。同样地通过fetch方法去读取文件。之所以采用读取文件流并传递arrayBuffer,是兼容批量数据,因为Web Worker的postMessage方法参数传值是会拷贝对象,如果之间传递普通json对象,会比传递arrayBuffer耗时。

    此外,还需要在主线程去定义一个Worker,接受Worker线程中发送的数据。其实现如下:

    function loadJSONByWorker({ url, cb }) {
      // cb为回调函数,处理文件
      const worker = new Worker("./js/web/worker/index.js");
      worker.postMessage({ type: "load", url });
      let receivedChunks = [];
      worker.onmessage = function (event) {
        if (event.data.error) {
          console.error("Worker error:", event.data.error);
        } else if (event.data.state) {
          let resBlob = new Blob(receivedChunks.flat());
          let reader = new FileReader();
          reader.readAsText(resBlob, "utf-8");
          reader.onload = () => {
            cb(JSON.parse(reader.result));
          };
        } else {
          receivedChunks.push(event.data); // 存储接受到的块
        }
      };
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    loadJSONByWorker方法主要就是定义 worker,传递参数,然后监听Worker线程的消息。当Worker线程arrayBuffer数据发送完后,会告诉主线程数据发送完成,主线程就会将arrayBuffer数据包装成Blob对象,然后通过FileReader的实例去读取Blob实例对象转换成文本字符串,最后调用JSON.parse转化为JSON对象。

    # 性能对比

    通过 Chrome 浏览器开发工具自带的 Lighthouse 和 performance 可以测试网页的性能表现。上述两种加载文件的方式,其数据对比如下

    # Lighthouse

    导航模式 测试类别:性能、最佳做法

    • 不使用Web Worker

    • 使用Web Worker

    时间跨度

    测试类别:性能、最佳做法

    • 不使用Web Worker

    • 使用Web Worker

    # Performance

    • 不使用Web Worker

    • 使用Web Worker

    # 结论

    从上述对比可以得出,Web Worker多线程编程总体上提高了网页的性能指标。

    编辑 (opens new window)
    上次更新: 2024/12/03, 06:54:15
    vue3中使用live2D
    vite配置打包分类文件

    ← vue3中使用live2D vite配置打包分类文件→

    最近更新
    01
    GeoJSON
    05-08
    02
    Circle
    04-15
    03
    CircleMarker
    04-15
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式