gpt4 book ai didi

javascript - 如何减慢 JavaScript 代码的执行速度?

转载 作者:行者123 更新时间:2023-12-01 02:21:38 25 4
gpt4 key购买 nike

我正在编写一个脚本来删除我所有的 YouTube 评论。这段代码的每一行都可以删除一个注释,但是当我将其放入循环中时,我收到一个 Uncaught TypeError: Cannot read property 'click' of undefined ,当我运行时,它不会出现每行单独。我在想,如果我能找到一种在代码行之间休眠的方法,我就可以消除错误。

var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");
for(i = 0; i < myList.length; i++) {
myList[i].click();
document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4].click(); //error here
document.getElementById("confirm-button").click();
}

我尝试使用 setTimeout,如下所示:

var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");
for(i=0; i<myList.length; i++) {
myList[i].click();
setTimeout(function(){document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4].click();}, 1000);
setTimeout(function(){document.getElementById("confirm-button").click();}, 5000);
}

它返回了数字279,但没有错误,也没有删除评论。发生了什么?

最佳答案

以下所有选项都有点“hackish” - 但没有一致且简单的方法可以在点击事件完全处理后获得通知。您可以将自己的单击事件监听器添加到目标元素,但是随后可以通过 stopPropagation 将其“静音”...即使这样,也没有(简单)的方法可以知道 DOM 何时完成“重绘”作为点击事件的结果 - 你可以看看使用 MutationObserver ,我猜

我假设(永远不要这样做) document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4] 所针对的元素通过单击 myList[i].click(); 动态添加这就是你遇到这个问题的原因。之后myList[i].click(); DOM 在“一段时间内”不会被“更新” - 所以,document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")很容易失败。

A potential issue is if deleting comments changes the number of elements targeted by document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer"); - as HTMLCollections are "live", removing a DOM element will mutate the HTMLCollection - only the last two code snippets will be immune to this possibility

因此,您可以通过四种不同的方式来实现此目的

<小时/>

选项 1 - ES5,只是简单的回调

var DELAY = 0; // try 0, then try increasing values
var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");
function confirmClick(callback3) {
document.getElementById("confirm-button").click();
setTimeout(callback3, DELAY);
}
function itemClick(callback2, callback3) {
document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4].click();
setTimeout(callback2, DELAY, callback3);
}
function listClick(element, callback1, callback2, callback3) {
element.click();
setTimeout(callback1, DELAY, callback2, callback3);
}
function doOne(i) {
listClick(myList[i], itemClick, confirmClick, function() {
++i;
if (i < myList.length) {
doOne(i);
}
});
}
doOne(0);
<小时/>

As you are trying to "chain" multiple asynchronous (sort of) processes together, Promise's (seem) to make the code a little less cumbersome

选项 2 - Promise,但带有嵌套 setTimeout的-使用Array#reduce将点击链接在一起,以便它们严格地一个接一个地处理

这太丑了,真的很丑,让金字塔建筑留给死去的埃及人,包括来说明我想要实现的目标

var DELAY = 0; // try 0, then try increasing values
var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");
var p = Promise.resolve();
for(i = 0; i < myList.length; i++) {
myList[i].click();
p = p.then(() => new Promise(resolve) => {
setTimeout(() => {
document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4].click();
setTimeout(() => {
document.getElementById("confirm-button").click();
setTimeout(resolve, DELAY);
}, DELAY);
}, DELAY);
});
}
<小时/>

选项 3 - Promise 带有辅助函数 - 基本上是上面的代码,但添加了辅助函数来防止金字塔

const DELAY = 0; // try 0, then try increasing values
const clickThenDelay = element => new Promise(resolve => {
element.click();
setTimeout(resolve, DELAY);
});
var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");

Array.from(myList).reduce((p, item) => {
return p
.then(() => clickThenDelay(item))
.then(() => clickThenDelay(document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4]))
.then(() => clickThenDelay(document.getElementById("confirm-button")))
}, Promise.resolve());
<小时/>

选项 4 - 与选项 3 类似,但此选项在触发单击之前添加了一个单击事件处理程序,该处理程序在“处理”单击后被删除。大概最后添加的处理程序是最后调用的。但不确定这是否得到保证。此外,如果较早的处理程序调用event.stop[Immediate]Propagation(),这将不起作用。

const DELAY = 0; // try 0, then try increasing values
const clickThenDelay = element => new Promise(resolve => {
const handleClick = () => {
element.removeEventListener('click', handleClick);
setTimeout(resolve, DELAY); // wait for repaint? Perhaps a MutationObserver event could be useful here?
}
element.addEventListener('click', handleClick);
element.click();
});
var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");

Array.from(myList).reduce((p, item) => {
return p
.then(clickThenDelay(item))
.then(() => clickThenDelay(document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4]))
.then(() => clickThenDelay(document.getElementById("confirm-button")))
}, Promise.resolve());

关于javascript - 如何减慢 JavaScript 代码的执行速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49164262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com