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

Node.js中如何让DOMPurify钩子的async/await操作同步生效

解决DOMPurify异步钩子执行时机问题

问题核心:DOMPurify的afterSanitizeElements钩子不支持异步操作——即便钩子函数声明为async,DOMPurify也不会等待其内部的Promise完成,导致sanitize方法返回HTML字符串时,图片的base64转换还未完成,最终输出的仍是原URL。

可行解决方案:先净化DOM,再手动异步处理图片

放弃钩子方案,改为先获取净化后的DOM对象,再遍历处理所有图片,确保所有异步操作完成后再转换为HTML字符串。

修改后的代码:

const { JSDOM } = require('jsdom');
const DOMPurify = require('dompurify')(new JSDOM().window);
const axios = require('axios');

// 正则判断网络图片URL
const regUrlWeb = /^https?:\/\//;

const getImageBase64 = async (url) => {
  try {
    const image = await axios.get(url, { responseType: 'arraybuffer' });
    // 补充data URI前缀,确保浏览器能识别base64图片
    const ext = url.split('.').pop().split('?')[0]; // 处理带参数的URL
    return `data:image/${ext};base64,${Buffer.from(image.data).toString('base64')}`;
  } catch (err) {
    console.error(`下载图片失败:${url}`, err);
    // 下载失败时保留原URL,也可替换为默认图片地址
    return url;
  }
};

// 1. 执行净化,返回DOM对象而非直接转成字符串
const sanitizedDom = DOMPurify.sanitize(dirty, { RETURN_DOM: true });

// 2. 获取所有img元素,并行异步处理src
const imgElements = sanitizedDom.querySelectorAll('img');
await Promise.all(Array.from(imgElements).map(async (img) => {
  if (img.hasAttribute('src') && regUrlWeb.test(img.src)) {
    const base64Src = await getImageBase64(img.src);
    img.setAttribute('src', base64Src);
  }
}));

// 3. 将处理后的DOM转换为HTML字符串
const clean = sanitizedDom.documentElement.innerHTML;
console.log(clean);

关键说明

  • 使用{ RETURN_DOM: true }选项,让DOMPurify返回完整DOM对象,而非直接输出HTML字符串;
  • 用Promise.all并行处理所有图片下载,提升整体处理效率;
  • 所有异步操作完成后再提取HTML内容,此时img的src已全部替换为base64格式。

内容的提问来源于stack exchange,提问作者Moisés Bites

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:40:54