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

How to catch an error on a async callback function on outer try/catch block

好的,

所以我正在使用 puppeteer 框架,并且我有一个与网页交互的异步函数。 该函数在等待页面流量空闲时点击和选择网页元素。 此功能大部分时间有效,但有时会停止。

我希望能够设置超时,这样如果该函数花费的时间超过一定时间,它就会抛出一个错误,我可以再次 运行 它。 到目前为止,我似乎无法让它工作,因为我无法使用外部函数获得传递给 setTimeOut() 到 'interact' 的回调函数。

我的代码如下所示:

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
    }
}

我还尝试按照 this postsetTimeOut 函数包装在 Promise 中,并使用 .then().catch() 回调尝试捕获错误但无济于事.

如果这是一个愚蠢的问题,我们深表歉意,感谢您的帮助。

尝试将 try 块中的所有内容变成承诺

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
    }
}

您 运行 遇到的问题本质上是 setTimeout() 中抛出的错误与您的函数流无关,因此无法在那里捕获。您基本上可以将计时器的回调函数视为“分离”函数:来自父作用域的变量仍然可用,但您不能 return 直接向父作用域等

要解决此问题,您有几种选择,Promise.race() 是一种可能的解决方案。这个想法是首先制作一个超时的异步版本:

const rejectAfter = (timeout) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => reject(), timeout);
  });
};

然后将您的业务逻辑提取到单独的异步函数中 a-la:

const doTheThing = async () => {
  // TODO: Implement
};

最后在你的抓取函数中,使用 Promise.race() 来使用两个先完成的结果:

const scrape = async (page) => {
  try {
    const el = await Promise.race([
      rejectAfter(1000),
      doTheThing()
    ]);
  } catch(error) {
    // TODO: Handle error
  }
}