在 puppeteer/JavaScript 中重试 page.goto、page.waitForNavigation 等的最佳实践

R0b*_*byn 2 javascript tor node.js async-await puppeteer

我正在尝试使用 Puppeteer 和 tor 包 ( apt install tor)在 TOR 网络中抓取一些网页。可能是由于 TOR 连接的性质,有时我会超时。另外,我是 JavaScript 异步编程的新手。

通常我有一个像这样的 try-catch-construct:

await Promise.all([
  page.goto(url),
  page.waitForNavigation({
    waitUntil: 'domcontentloaded'
  }),
]).catch((err) => { logMyErrors(err, true); });
Run Code Online (Sandbox Code Playgroud)

或者

let langMenu = await page.waitForXPath('//*[contains(@class, ".customer_name")]/ancestor::li').catch((err) => { logMyErrors(err, true); });
Run Code Online (Sandbox Code Playgroud)

但我认为通常一次或多次重试将有助于最终获得所需的资源。是否有实施重试的最佳实践?

Tho*_*orf 10

我会推荐这种相当简单的方法:

async function retry(promiseFactory, retryCount) {
  try {
    return await promiseFactory();
  } catch (error) {
    if (retryCount <= 0) {
      throw error;
    }
    return await retry(promiseFactory, retryCount - 1);
  }
}
Run Code Online (Sandbox Code Playgroud)

此函数调用promiseFactory, 并等待返回的 Promise 完成。如果发生错误,该过程将(递归地)重复,直到retryCount达到0

代码示例

您可以像这样使用该函数:

await retry(
  () => page.waitForXPath('//*[contains(@class, ".customer_name")]/ancestor::li'),
  5 // retry this 5 times
);
Run Code Online (Sandbox Code Playgroud)

您还可以传递任何其他返回 Promise 的函数,例如Promise.all

await retry(
  () => Promise.all([
    page.goto(url),
    page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
  ]),
  1 // retry only once
);
Run Code Online (Sandbox Code Playgroud)

不要结合 await 和 catch

另一个建议:您不应await.then或结合使用,.catch因为这会导致意外问题。使用块或使用和await包围您的代码。否则您的代码可能正在等待函数的结果完成等。try..catch.then.catchcatch

相反,您可以try..catch这样使用:

try {
  // ...
} catch (error) {
  logMyErrors(error);
}
Run Code Online (Sandbox Code Playgroud)