Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/412.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何降低JavaScript代码的执行速度?_Javascript_Youtube - Fatal编程技术网

如何降低JavaScript代码的执行速度?

如何降低JavaScript代码的执行速度?,javascript,youtube,Javascript,Youtube,我正在写一个脚本来删除我在YouTube上的所有评论。这段代码的每一行都可以删除一条注释,但当我将其放入循环中时,会得到一个未捕获的TypeError:cannotread属性“click”of undefined,当我单独运行每一行时,该属性不会出现。我在想,如果我能想出一种在代码行之间休眠的方法,我就可以消除错误 var myList = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-render

我正在写一个脚本来删除我在YouTube上的所有评论。这段代码的每一行都可以删除一条注释,但当我将其放入循环中时,会得到一个
未捕获的TypeError:cannotread属性“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();
}
var myList=document.getElementsByClassName(“下拉触发器样式范围ytd菜单渲染器”);
对于(i=0;i
我尝试使用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);
}
var myList=document.getElementsByClassName(“下拉触发器样式范围ytd菜单渲染器”);

对于(i=0;i而言,罪魁祸首是自从您执行
函数以来,页面一直没有时间更新DOM。单击()
函数。您需要给它时间,可能是在下面的解决方案中使用
requestAnimationFrame
或不太精确的
setTimeout
。(完全未经测试,现场制作),进程是在暂停后执行每个操作(打开下拉列表,单击删除,确认),以给DOM时间进行更新。请考虑:

function deleteAllComments ( ) {
    'use strict';
    var commentsToDelete, i;

    function openNextCommentOptionsDropdown ( ) {
        if ( ! (++i < commentsToDelete.length ) ) {
            console.log('No more comments to remove.');
            return;
        }

        commentsToDelete[i].click();
        setTimeout(activateCommentDeleteButton, 50);
    }

    function activateCommentDeleteButton ( ) {
        var el = document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4];

        if ( ! el ) {
            console.warn('No "Delete" button found, at comment #', i, commentsToDelete[i]);
            console.log('Stopping delete operation');
            return;
        }

        el.click();
        setTimeout(activateCommentDeleteConfirmationButton, 50);
    }

    function activateCommentDeleteConfirmationButton ( ) {
        var el = document.getElementById("confirm-button");

        if ( ! el ) {
            console.warn('Unable to confirm comment delete action, at comment #', i, commentsToDelete[i]);
            console.log('Stopping delete operation');
            return;
        }

        el.click();
        setTimeout(openNextCommentOptionsDropdown, 50); // continue larger "loop"
    }

    commentsToDelete = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");

    openNextCommentOptionsDropdown(); // start the "loop"
}
函数deleteAllComments(){
"严格使用",;
var,删除,i;
函数OpenNextCommonOptions下拉列表(){
如果(!(++i
这里有两大细节:

  • 为DOM提供更新时间以响应代码已启动的操作(
    setTimeout(…,50)
    ,其中50ms应该足够长;根据需要减少,或者只使用
    requestAnimationFrame

  • 防御性编码:在对返回的项目盲目执行函数之前,首先检查项目是否确实存在(
    if(!el){…}


  • 罪魁祸首是,自从您执行
    .click()
    函数以来,页面一直没有时间更新DOM。您需要给它时间,可能是使用
    requestAnimationFrame
    或下面解决方案中精度较低的
    setTimeout
    。(完全未经测试,现场制作),进程是在暂停后执行每个操作(打开下拉列表,单击删除,确认),以给DOM时间进行更新。请考虑:

    function deleteAllComments ( ) {
        'use strict';
        var commentsToDelete, i;
    
        function openNextCommentOptionsDropdown ( ) {
            if ( ! (++i < commentsToDelete.length ) ) {
                console.log('No more comments to remove.');
                return;
            }
    
            commentsToDelete[i].click();
            setTimeout(activateCommentDeleteButton, 50);
        }
    
        function activateCommentDeleteButton ( ) {
            var el = document.getElementsByClassName("style-scope ytd-menu-navigation-item-renderer")[4];
    
            if ( ! el ) {
                console.warn('No "Delete" button found, at comment #', i, commentsToDelete[i]);
                console.log('Stopping delete operation');
                return;
            }
    
            el.click();
            setTimeout(activateCommentDeleteConfirmationButton, 50);
        }
    
        function activateCommentDeleteConfirmationButton ( ) {
            var el = document.getElementById("confirm-button");
    
            if ( ! el ) {
                console.warn('Unable to confirm comment delete action, at comment #', i, commentsToDelete[i]);
                console.log('Stopping delete operation');
                return;
            }
    
            el.click();
            setTimeout(openNextCommentOptionsDropdown, 50); // continue larger "loop"
        }
    
        commentsToDelete = document.getElementsByClassName("dropdown-trigger style-scope ytd-menu-renderer");
    
        openNextCommentOptionsDropdown(); // start the "loop"
    }
    
    函数deleteAllComments(){
    "严格使用",;
    var,删除,i;
    函数OpenNextCommonOptions下拉列表(){
    如果(!(++i
    这里有两大细节:

  • 为DOM提供更新时间以响应代码已启动的操作(
    setTimeout(…,50)
    ,其中50ms应该足够长;根据需要减少,或者只使用
    requestAnimationFrame

  • 防御性编码:在对返回的项目盲目执行函数之前,首先检查项目是否确实存在(
    if(!el){…}


  • 下面的所有选项都有点“黑客”——但当点击事件被完全处理时,没有一致且简单的方式获得通知。 您可以将自己的click事件侦听器添加到目标元素,但是,可以通过StopRopagation将其“静音”。。。 即使这样,也没有(简单的)方法知道DOM何时完成了由于单击事件而导致的“重新绘制”——您可以使用 我
    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);
        });
    }
    
    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());
    
    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());