[英]How can I make jQuery replaceWith() “non-blocking” (async)?
我正在使用 function replaceStr()
替换正文标记中的一些字符串。 如果 html 页面较小,则更换不明显。 但是,如果 html 页面更大更复杂,您会注意到它。 替换正在阻止浏览器。 我的问题,如何使替换非阻塞? 替换对页面并不重要,因此它可以在浏览器不忙时在后台发生。 我尝试使用async和await ,但我认为replaceWith()
function 无法处理 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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.