简体   繁体   English

如何在外部 try/catch 块上的异步回调 function 上捕获错误

[英]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.

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