Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/416.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_Promise_Automation - Fatal编程技术网

Javascript 如何处理承诺递归

Javascript 如何处理承诺递归,javascript,promise,automation,Javascript,Promise,Automation,我有一个用javascript编写的自动化脚本,它应该完成的任务是点击Get Tasks按钮,它触发ajax调用,调用结果显示在表中,下一步是检查表,如果有任务,脚本通过点击Accept按钮接受,否则,脚本单击获取任务按钮。 任务似乎很简单,所以我编写了以下脚本: function clickGetTasksButton() { return new Promise(resolve => { document.getElementsByClassName("get-

我有一个用javascript编写的自动化脚本,它应该完成的任务是点击
Get Tasks
按钮,它触发ajax调用,调用结果显示在表中,下一步是检查表,如果有任务,脚本通过点击
Accept
按钮接受,否则,脚本单击获取任务按钮。 任务似乎很简单,所以我编写了以下脚本:

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
        });
    });
}
我正在努力添加以下逻辑: 如果有
接受
按钮,则单击该按钮,否则单击
获取任务
按钮并重复。
我曾想过使用递归,但我担心在某个时候它会引发堆栈溢出异常。

您可以从
.then()
处理程序自由递归。因为堆栈在调用
.then()
处理程序之前已经完全展开,所以当您再次调用
驱动程序()
或从
.then()
处理程序中调用任何其他顶级函数时,都不会出现堆栈堆积

例如,您可以执行以下操作:

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();
            }
        });
    });
}
或者稍微变平一点:

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();
        }
    });
}

还要注意,
clickGetTaskButton
不需要返回承诺,因为它看起来是完全同步的。此外,您不能直接调用
。在
文档的结果上单击()
。GetElementsByCassName()
。该函数返回一个类似数组的列表(一个
HTMLCollection
对象),该列表没有
.click()
方法。我不知道您是否打算获取该列表中的第一个DOM元素并调用
。单击它()
,或者是否要循环调用每个元素的
。单击()


而且,您的
setInterval()
应该使用比50ms更长的间隔。你想给网页本身一些周期来完成它的工作。你在这里每秒敲20次。我会说将它设置为像
200
这样的值。而且,希望这不会花费很长时间来运行,因为如果这是一个移动设备,这将影响电池寿命,甚至可能被主机浏览器抢占(以节省电池)。

您可以从
.then()
处理程序自由递归。因为堆栈在调用
.then()
处理程序之前已经完全展开,所以当您再次调用
驱动程序()
或从
.then()
处理程序中调用任何其他顶级函数时,都不会出现堆栈堆积

例如,您可以执行以下操作:

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();
            }
        });
    });
}
或者稍微变平一点:

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();
        }
    });
}

还要注意,
clickGetTaskButton
不需要返回承诺,因为它看起来是完全同步的。此外,您不能直接调用
。在
文档的结果上单击()
。GetElementsByCassName()
。该函数返回一个类似数组的列表(一个
HTMLCollection
对象),该列表没有
.click()
方法。我不知道您是否打算获取该列表中的第一个DOM元素并调用
。单击它()
,或者是否要循环调用每个元素的
。单击()


而且,您的
setInterval()
应该使用比50ms更长的间隔。你想给网页本身一些周期来完成它的工作。你在这里每秒敲20次。我会说将它设置为像
200
这样的值。而且,希望这不会花费很长时间来运行,因为如果这是一个移动设备,这将影响电池寿命,甚至可能被主机浏览器抢占(以节省电池)。

单击GetTaskButton()。然后(waitForSpinner)。然后((结果)=>{})记住,承诺是可链接的,这样做是为了避免深度嵌套回调。而且,像
ClickGetTaskButton()
这样纯粹同步的东西可能只是一个普通函数。根本不需要用承诺来包装它。谢谢你的建议,但是我如何处理我在问题中描述的逻辑呢?你可以从
.then()
处理程序自由递归。因为堆栈在调用
.then()
处理程序之前已经完全展开,所以当您再次调用
驱动程序()
或从
.then()
处理程序中调用任何其他顶级函数时,都不会出现堆栈堆积。
单击gettasksbutton()。然后(waitForSpinner)。然后((结果)=>{})记住,承诺是可链接的,这样做是为了避免深度嵌套回调。而且,像
ClickGetTaskButton()
这样纯粹同步的东西可能只是一个普通函数。根本不需要用承诺来包装它。谢谢你的建议,但是我如何处理我在问题中描述的逻辑呢?你可以从
.then()
处理程序自由递归。因为堆栈在调用
.then()
处理程序之前已经完全展开,所以当您再次调用
驱动程序()
或从
.then()
处理程序中调用任何其他顶级函数时,都不会出现堆栈堆积。