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

如何在用户脚本中替换已弃用的同步XMLHttpRequest?

解决Worker代码加载的跨域问题(非文件方式)

完全可以通过字符串或模板字面量直接为Worker提供代码,核心是将代码转为Blob对象生成同源URL,绕开外部文件的跨域限制,同时解决同步XHR的性能和弃用问题。

具体实现思路

  • 将Worker的业务逻辑(比如异步获取包页面、解析类型分类)写成模板字面量字符串
  • 把字符串转为Blob对象,指定MIME类型为text/javascript
  • 用URL.createObjectURL生成Blob的本地可访问URL,以此创建Worker实例

示例代码

// 定义Worker要执行的代码(模板字面量形式)
const workerLogic = `
self.onmessage = async (event) => {
  const packagePageUrl = event.data;
  try {
    // 用异步fetch替代同步XHR,避免主线程阻塞
    const response = await fetch(packagePageUrl);
    const pageHtml = await response.text();
    
    // 解析HTML提取类型分类(I、C、Eₙ、Eₓ、Eᵣ、A)
    const typeGroups = parseTypeCategories(pageHtml);
    
    // 将结果发回主线程
    self.postMessage({ success: true, data: typeGroups });
  } catch (err) {
    self.postMessage({ success: false, error: err.message });
  }
};

// 实现HTML解析逻辑(Worker内可用DOMParser)
function parseTypeCategories(html) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(html, 'text/html');
  const typeTable = doc.querySelector('table.summary-table');
  const rows = typeTable?.querySelectorAll('tr') || [];
  
  const groups = {
    interfaces: [],
    classes: [],
    enums: [],
    exceptions: [],
    errors: [],
    annotations: []
  };
  
  rows.forEach(row => {
    const typeLink = row.querySelector('a');
    const typeName = typeLink?.textContent.trim();
    if (!typeName) return;
    
    const typeDesc = row.querySelector('td.col-last')?.textContent.trim() || '';
    // 根据描述判断类型分类,比如"interface"对应I,"class"对应C等
    if (typeDesc.includes('interface')) groups.interfaces.push(typeName);
    else if (typeDesc.includes('class')) groups.classes.push(typeName);
    else if (typeDesc.includes('enum')) groups.enums.push(typeName);
    else if (typeDesc.includes('exception')) groups.exceptions.push(typeName);
    else if (typeDesc.includes('error')) groups.errors.push(typeName);
    else if (typeDesc.includes('annotation')) groups.annotations.push(typeName);
  });
  
  return groups;
}
`;

// 创建Blob并生成Worker URL
const codeBlob = new Blob([workerLogic], { type: 'text/javascript' });
const workerUrl = URL.createObjectURL(codeBlob);
const typeParserWorker = new Worker(workerUrl);

// 主线程与Worker通信
typeParserWorker.postMessage('https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/package-summary.html');
typeParserWorker.onmessage = (event) => {
  if (event.data.success) {
    // 用解析出的分类数据构建导航树
    buildNavTree(event.data.data);
  } else {
    console.error('类型解析失败:', event.data.error);
  }
  // 释放URL资源,避免内存泄漏
  URL.revokeObjectURL(workerUrl);
  typeParserWorker.terminate();
};

// 导航树构建函数(主线程执行,操作DOM)
function buildNavTree(typeGroups) {
  // 你的导航树生成逻辑,比如创建DOM节点插入页面
  console.log('类型分类结果:', typeGroups);
}

核心优势

  • 无需外部Worker文件,代码完全内嵌在用户脚本中
  • Blob URL属于同源范围,不会触发跨域安全错误
  • 异步fetch替代同步XHR,彻底解决主线程阻塞和浏览器弃用警告问题

注意事项

  • Worker内部无法直接操作DOM,所有DOM修改必须回到主线程处理
  • 任务完成后务必调用URL.revokeObjectURL释放Blob URL资源
  • 确保解析逻辑在Worker环境中兼容(比如使用DOMParser而非直接访问页面DOM)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:37:54