如何使 jQuery replaceWith() "non-blocking" (异步)?
How can I make jQuery replaceWith() "non-blocking" (async)?
我正在使用函数 replaceStr()
来替换 body 标签中的一些字符串。如果 html 页面很小,则替换不明显。但是,如果 html 页面更大更复杂,您就会注意到它。替换是阻塞 浏览器。我的问题是,如何使替换 非阻塞 成为可能?替换对页面来说并不重要,所以它可以在后台发生,当浏览器不忙时。我尝试使用 async 和 await,但我认为 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);
}
}
我正在使用函数 replaceStr()
来替换 body 标签中的一些字符串。如果 html 页面很小,则替换不明显。但是,如果 html 页面更大更复杂,您就会注意到它。替换是阻塞 浏览器。我的问题是,如何使替换 非阻塞 成为可能?替换对页面来说并不重要,所以它可以在后台发生,当浏览器不忙时。我尝试使用 async 和 await,但我认为 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);
}
}