[英]How to catch an error on a async callback function on outer try/catch block
Ok,行,
So I am using the puppeteer framework and I have an async function that interact with a webpage.所以我正在使用 puppeteer 框架,并且我有一个与网页交互的异步 function。 This function clicks and selects and elements of a webpage while it waiting for the traffic of the page to be idle.
此 function 在等待页面流量空闲时点击并选择网页元素。 This function works most of the time, but sometimes it stalls.
这个 function 大部分时间都有效,但有时会停止。
I want to be able to set a timeout so that if the function is taking longer than a certain amount of time, it throws an error and I can run it again.我希望能够设置超时,这样如果 function 花费的时间超过一定时间,它就会抛出错误,我可以再次运行它。 So far I cannot seem to get this to work because I cannot get the callback function I pass to
setTimeOut()
to 'interact' with the outer function.到目前为止,我似乎无法让它工作,因为我无法获得传递给 setTimeOut
setTimeOut()
的回调 function 以与外部 function 进行“交互”。
My code looks like this:我的代码如下所示:
const scrap_webtite = async page => {
/* scrap the site */
try{ // catch all
// set timeout
let timed_out_ID = setTimeout(()=> throw "timeOut", 1000);
// run the async
let el = await sometimes_stalls_function(page);
// if function ran finished correcly
clearTimeout(timed_out_ID);
// save el
save_el(el);
}
}catch(e){
console.error("Something went wrong!", e);
// this makes the function run again
// here is where I want to ideally catch the timeout error
return false
}
}
I have also tried wrapping the setTimeOut
function in an Promise
as per this post and the using the .then().catch()
callbacks to try to catch the error to no avail.我还尝试按照这篇文章将
setTimeOut
function 包装在Promise
中,并使用 .then .then().catch()
回调尝试捕获错误但无济于事。
Apologies if this is a stupid question, thank for you help.抱歉,如果这是一个愚蠢的问题,谢谢你的帮助。
try turning everything in the try
block into a promise尝试将
try
块中的所有内容变成 promise
const scrap_webtite = async page => {
/* scrap the site */
try{ // catch all
return await new Promise(async(r,j)=>{
// set timeout
let timed_out_ID = setTimeout(()=>j("timeOut"),1000);
// run the async
let el = await sometimes_stalls_function(page);
// if function ran finished correcly
clearTimeout(timed_out_ID);
// save el
r(save_el(el));
})
}catch(e){
console.error("Something went wrong!", e);
// this makes the function run again
// here is where I want to ideally catch the timeout error
return false
}
}
The problem you're running into is essentially that the error thrown in setTimeout()
is not related to your function flow, and thus can't be caught there.您遇到的问题本质上是
setTimeout()
中抛出的错误与您的 function 流程无关,因此无法在那里捕获。 You can essentially think of the timer's callback function as a "detached" function: the variables from the parent scope will still be available, but you can't return
a value to the parent directly etc.您基本上可以将计时器的回调 function 视为“分离的”function:来自父级 scope 的变量仍然可用,但您不能直接向父级
return
值等。
To work around this problem you have a few options, Promise.race()
is one possible solution.要解决此问题,您有几种选择,
Promise.race()
是一种可能的解决方案。 The idea is to first make an async version of a timeout:这个想法是首先制作一个超时的异步版本:
const rejectAfter = (timeout) => {
return new Promise((resolve, reject) => {
setTimeout(() => reject(), timeout);
});
};
Then extract your business logic out into a separate async function a-la:然后将您的业务逻辑提取到单独的异步 function a-la 中:
const doTheThing = async () => {
// TODO: Implement
};
And finally in your scraping function, use Promise.race()
to use the result from whichever of the two finishes first:最后在你的抓取 function 中,使用
Promise.race()
来使用两个先完成的结果:
const scrape = async (page) => {
try {
const el = await Promise.race([
rejectAfter(1000),
doTheThing()
]);
} catch(error) {
// TODO: Handle error
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.