You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript实时监测网页加载字节数?解决大资源更新停顿问题

实时监测网页加载字节数的解决方案

你当前用PerformanceObserver的方式只能在资源完全加载完成后触发更新,对于大体积资源(如WebGL模型),加载过程中会出现长时间的进度停顿——这是因为Resource Timing API仅提供资源加载完成后的统计数据,无法获取中间加载状态。

下面提供两种可行的实时监控方案:

方案1:手动管控自主发起的资源请求

如果是你通过代码主动加载的资源(比如WebGL 3D模型、自定义脚本),可以直接用XMLHttpRequest的progress事件监听实时加载进度,累加已加载字节数:

let totalBytes = 12295985; // 预设总字节数
let loadedBytes = 0;

// 封装带进度监听的资源加载函数
function loadResource(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'blob'; // 根据资源类型调整(如text、arraybuffer)

    // 记录上一次进度的已加载字节,避免重复累加
    let prevLoaded = 0;
    xhr.addEventListener('progress', (e) => {
      if (e.lengthComputable) {
        loadedBytes += e.loaded - prevLoaded;
        prevLoaded = e.loaded;
        updateProgress();
      }
    });

    xhr.addEventListener('load', () => resolve(xhr.response));
    xhr.addEventListener('error', reject);
    xhr.send();
  });
}

// 更新进度(可替换为DOM操作更新页面进度条)
function updateProgress() {
  const progressRate = (loadedBytes / totalBytes) * 100;
  console.log(`已加载:${loadedBytes}字节 | 进度:${progressRate.toFixed(2)}%`);
}

// 调用示例:加载WebGL模型
loadResource('/path/to/your-large-model.glb');

方案2:拦截页面自动加载的资源

如果是页面中通过<img>、<script>等标签自动加载的资源,可以用MutationObserver监听DOM元素新增,替换为手动XHR加载并监听进度:

let totalBytes = 12295985;
let loadedBytes = 0;
const loadedResources = new Set(); // 去重,避免重复统计缓存资源

// 监听DOM新增元素
const domObserver = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    mutation.addedNodes.forEach(node => {
      if (node.tagName === 'IMG' && node.src) handleImage(node);
      if (node.tagName === 'SCRIPT' && node.src) handleScript(node);
      // 可扩展处理<link>、<audio>等其他资源类型
    });
  });
});

domObserver.observe(document.documentElement, { childList: true, subtree: true });

// 处理图片资源
function handleImage(img) {
  const src = img.src;
  if (loadedResources.has(src)) return;
  loadedResources.add(src);

  const xhr = new XMLHttpRequest();
  xhr.open('GET', src);
  xhr.responseType = 'blob';

  let prevLoaded = 0;
  xhr.addEventListener('progress', e => {
    if (e.lengthComputable) {
      loadedBytes += e.loaded - prevLoaded;
      prevLoaded = e.loaded;
      updateProgress();
    }
  });

  xhr.addEventListener('load', () => {
    const blobUrl = URL.createObjectURL(xhr.response);
    img.src = blobUrl;
    img.onload = () => URL.revokeObjectURL(blobUrl); // 释放Blob URL
  });

  img.removeAttribute('src'); // 阻止浏览器自动加载
  xhr.send();
}

// 处理脚本资源
function handleScript(script) {
  const src = script.src;
  if (loadedResources.has(src)) return;
  loadedResources.add(src);

  const xhr = new XMLHttpRequest();
  xhr.open('GET', src);
  xhr.responseType = 'text';

  let prevLoaded = 0;
  xhr.addEventListener('progress', e => {
    if (e.lengthComputable) {
      loadedBytes += e.loaded - prevLoaded;
      prevLoaded = e.loaded;
      updateProgress();
    }
  });

  xhr.addEventListener('load', () => {
    const newScript = document.createElement('script');
    newScript.textContent = xhr.response;
    script.parentNode.replaceChild(newScript, script);
  });

  script.removeAttribute('src');
  xhr.send();
}

function updateProgress() {
  const progressRate = (loadedBytes / totalBytes) * 100;
  console.log(`已加载:${loadedBytes}字节 | 进度:${progressRate.toFixed(2)}%`);
}

关键注意点

  • 跨域资源需要服务器配置Access-Control-Allow-Origin,否则XHR无法获取资源进度。
  • 总字节数如果需要自动计算,可通过HEAD请求批量获取所有资源的Content-Length并累加,但同样受跨域限制。
  • 用Set或Map记录已加载资源,避免缓存资源被重复统计。

内容的提问来源于stack exchange,提问作者Panoman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:35:16