简体   繁体   English

如何处理承诺递归

[英]How to handle promise recursions

I have a automated script written in javascript, the task it should accomplish is to click on Get Tasks button, which triggers ajax call and results of the call are displayed in table, the next step is to check the table, if there is a task, script accepts it by clicking on Accept button, else, script clicks on Get Tasks button.我有一个用javascript编写的自动化脚本,它应该完成的任务是点击Get Tasks按钮,触发ajax调用,调用结果显示在表格中,下一步是检查表格,如果有任务, 脚本通过单击Accept按钮接受它,否则,脚本单击Get Tasks按钮。 Task seems simple so I wrote following script:任务看起来很简单,所以我写了以下脚本:

function clickGetTasksButton() {
    return new Promise(resolve => {
        document.getElementsByClassName("get-tasks-btn").click();
        resolve();
    });
}
function waitForSpinner() {
    return new Promise((resolve) => {
        let spinInterval = setInterval(() => {
            let spinner = document.querySelector('.spinner');
            if (!spinner) {
                console.log("Spinner is gone... ");
                clearInterval(spinInterval);
                resolve(document.getElementsByClassName("task-card").length > 0)
            }
        }, 50)
    });
}
function driver() {
    clickGetTasksButton().then(() => {
        waitForSpinner().then((result) => {
            //Script should either accept task or repeat the whole process
        });
    });
}

I am struggling with adding following logic: if there is Accept button, then click on it, else click on Get Tasks button and repeat.我正在努力添加以下逻辑:如果有Accept按钮,则单击它,否则单击Get Tasks按钮并重复。 I thought of using recursions, but I am afraid that at some point it will throw stack overflow exception.我想过使用递归,但我担心在某些时候它会抛出堆栈溢出异常。

You can just freely recurse from a .then() handler.您可以从.then()处理程序中自由递归。 Because the stack has already completely unwound before a .then() handler is called, there is no stack buildup when you just call driver() again or whatever other top level function you want to call from within a .then() handler.因为在调用.then()处理程序之前堆栈已经完全展开,所以当您再次调用driver()或您想从.then()处理程序中调用的任何其他顶级函数时,不会建立堆栈。

For example, you can do this:例如,您可以这样做:

function driver() {
    return clickGetTasksButton().then(() => {
        waitForSpinner().then((result) => {
            //Script should either accept task or repeat the whole process
            if (taskWaiting) {
                return processTasks();
            } else {
                return driver();
            }
        });
    });
}

or flattened a bit:或压扁一点:

function driver() {
    return clickGetTasksButton().then(waitForSpinner).then(result => {
        //Script should either accept task or repeat the whole process
        if (taskWaiting) {
            return processTasks();
        } else {
            return driver();
        }
    });
}

Also note that clickGetTasksButton does not need to return a promise as it appears to be entirely synchronous.另请注意, clickGetTasksButton不需要返回承诺,因为它似乎是完全同步的。 Also, you can't directly call .click() on the results of document.getElementsByClassName() .此外,您不能直接对document.getElementsByClassName()的结果调用.click() document.getElementsByClassName() That function returns an array-like list (an HTMLCollection object) that doesn't have a .click() method.该函数返回一个类似数组的列表(一个HTMLCollection对象),它没有HTMLCollection .click()方法。 I don't know whether you intend to get the first DOM element in that list and call .click() on it or if you want to loop through the list calling .click() on each one.我不知道您是否打算获取该列表中的第一个 DOM 元素并对其调用.click() ,或者您是否想遍历列表,在每个.click()上调用.click()

And, your setInterval() should probably use a bit longer interval than 50ms.而且,您的setInterval()应该使用比 50 毫秒更长的间隔。 You want to give some cycles to the webpage itself to do its job.你想给网页本身一些循环来完成它的工作。 You're kind of hammering it here 20 times per second.你在这里每秒敲击它 20 次。 I'd say set it to something like 200 .我会说将它设置为200东西。 And, hopefully this doesn't take long to run because if this is a mobile device, this will hammer battery life and maybe even get pre-empted by the host browser (to save battery).而且,希望这不会花费很长时间运行,因为如果这是一个移动设备,这将影响电池寿命,甚至可能被主机浏览器抢占(以节省电池)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM