javascript - 在继续执行下一行代码之前等待异步递归函数完成
问题描述
我正在尝试等待递归函数完全完成,然后再继续执行下一行代码。我正在使用 PuppeteerJS 在页面上查找项目,如果该项目不存在,3 秒后重新加载页面并重试。在继续之前,我需要完成此功能。我在下面尝试实现的简单代码示例。
(async () => {
await waitForThisToFinish() // Wait for this function no matter how long it takes
console.log("Don't log until function has completed")
})()
async function waitForThisToFinish() {
try {
await findItemOnPage() //function times out after 3 seconds
}
catch (ex) {
// If Item is not found after 3 seconds an error is thrown.
// Catch error and reload page to see if item has been loaded and look again.
waitForThisToFinish() //recursive call
}
}
目前,如果第一次尝试未找到该项目,则会引发错误并成功开始递归。但是,代码执行会继续,并且不会等待函数成功完成。
有没有办法让'catch'无法解决?我需要从 waitForThisToFinish() 函数返回一个承诺吗?这将如何与递归一起工作?任何帮助,将不胜感激。
解决方案
我建议使用一个循环,当成功时你会中断,因为这样就不会以任何方式(如承诺)建立资源,并且如果需要,你可以无限次调用你的函数,而不会强调资源使用。
async function waitForThisToFinish() {
while (true) {
try {
let val = await findItemOnPage()
// use break or return here to break out of the loop
return val;
} catch (ex) {
console.log("still waiting and trying again")
}
}
}
此外,您还应该进行一些额外的更改:
- 检查实际错误以确保它是可以通过重试修复的错误类型(例如超时)。如果这是一个永久性错误,您将永远重试。
- 在重试之前实施延迟以避免在服务器端造成雪崩故障并避免服务器因速率限制而阻塞。
- 在延迟中实施渐进式退避。
因为您通常不想编写代码来敲击服务器(通过快速连续地反复发出相同的请求),因为这可能会导致雪崩服务器故障,一个小问题变成一个大问题非常很快,您可能应该在重试之前实施延迟,问题持续的时间越长,延迟就会越长。
function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}
async function waitForThisToFinish() {
let waitTime = 100;
while (true) {
try {
let val = await findItemOnPage()
// use break or return here to break out of the loop
return val;
} catch (ex) {
// Should also check if the actual error is one that is likely
// temporary. Otherwise, you may loop forever on a permanent error
console.log("still waiting and trying again")
// implement super simple backoff (there are much more elegant algorithms available)
await delay(waitTime);
waitTime += 300;
}
}
}
推荐阅读
- c# - 如何从另一个场景中的脚本访问保存/加载功能?
- love2d - 错误 main.lua:138:尝试调用方法“checkCollision”(一个零值)
- go - 初始化嵌套匿名结构
- angular - 在 sidenav 中编辑表单后重新获取/重新加载组件中的数据
- python-3.x - 内存错误无法分配 array.shape
- c - 有麻烦的运行代码。代码必须由用户在另一个函数中使用指针删除给定语句中的元音。任何帮助表示赞赏
- c++ - 实现编译检查以避免 C++ 中的嵌套作用域
- javascript - 在另一个方法内部调用后异步方法显示没有进度
- database - 根据oracle中嵌套表中不区分大小写的匹配对结果进行排名
- c# - 我可以在不使用 for 循环的情况下为数组中的每个字符串添加一个字符串吗?