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