如何使 jQuery replaceWith() "non-blocking" (异步)?

How can I make jQuery replaceWith() "non-blocking" (async)?

我正在使用函数 replaceStr() 来替换 body 标签中的一些字符串。如果 html 页面很小,则替换不明显。但是,如果 html 页面更大更复杂,您就会注意到它。替换是阻塞 浏览器。我的问题是,如何使替换 非阻塞 成为可能?替换对页面来说并不重要,所以它可以在后台发生,当浏览器不忙时。我尝试使用 asyncawait,但我认为 replaceWith() 函数无法处理 Promises,这就是它无法使用的原因async/await。但是那怎么办呢?

function replaceStr(myStrArr) {
  const container = $('body :not(script)');
  myStrArr.map((mystr) => {
    container
      .contents()
      .filter((_, i) => {
        return i.nodeType === 3 && i.nodeValue.match(mystr.reg);
      })
      .replaceWith(function () {
        return this.nodeValue.replace(mystr.reg, mystr.newStr);
      });
  });
}

感谢您的帮助。

您当前的实施有几个地方可以在进入异步路线之前进行优化。例如,您可以摆脱 jQuery 依赖项。它对您的情况没有多大帮助,但会增加开销。

然后当前你正在映射你的替换和所有候选节点中的每一个,每次替换 nodeValue。这可能每次都会触发重绘。

相反,您可以使用 TreeWalker 快速遍历相关节点,并且只更新 nodeValues 一次。


在我的测试中,以下代码的运行速度大约比您当前的代码快 16 倍。也许这已经足够了?

function replaceStr_upd(replacements) {
    // create a tree walker for all text nodes
    const it = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
        // but skip SCRIPTs
        acceptNode: node => node.parentNode.nodeName === 'SCRIPT'
                            ? NodeFilter.FILTER_REJECT
                            : NodeFilter.FILTER_ACCEPT
    });

    // a helper function
    const applyReplacements = initial => replacements.reduce((text, r) => text.replace(r.reg, r.newStr), initial);

    // iterate over all text node candidates
    while (it.nextNode()) {
        // but only update once per node:
        it.currentNode.nodeValue = applyReplacements(it.currentNode.nodeValue);
    }
}