【问题标题】:Proper way to use page.waitForNavigation in Puppeteer [duplicate]在 Puppeteer 中使用 page.waitForNavigation 的正确方法 [重复]
【发布时间】:2019-02-07 17:41:02
【问题描述】:

我对@9​​87654321@ 有点困惑。我知道它是什么以及它做了什么,但我会根据互联网速度得到不同的结果(这就是我认为的因素)。

想象一下这段代码:

await page.$eval('#username', (el , setting ) => el.value = setting.username , setting );
await page.$eval('#password', (el , setting ) => el.value = setting.password , setting );
await page.$eval('form', form => form.submit());
await page.waitForNavigation();
await page.goto( 'http://example.com/dashboard'  );

填写登录表单,提交登录表单,等待表单提交,然后重定向到仪表板。

这在我的 localhost 上运行良好,它的网速较慢(与服务器相比),但是当我将它上传到服务器时,我得到了

Error: Navigation Timeout Exceeded: 30000ms exceeded 

在服务器上,如果我从代码中删除 await page.waitForNavigation(); 并被重定向到仪表板,它会正常工作。

但现在在 localhost 上,我在提交表单之前被重定向到仪表板。我得到you cant see dashboard , your not logged in 或类似的东西。

我认为决定因素是互联网的速度。

在服务器上,我的速度非常快,因此表单会立即提交,并且在 await page.waitForNavigation() 行之前完成,所以我收到导航超时错误。

但是在速度较慢的本地主机上,表单需要更多的时间来提交,所以我需要在提交表单后有await page.waitForNavigation(),否则我会在表单有机会提交之前被重定向到仪表板。

我正在寻求有更多与 Puppeteer 合作经验的人提供有关如何处理这种情况的建议。现在,我在服务器或本地主机上运行时一直在编辑我的代码,这很有效,但是很烦人!

使用后

async function open_tab(setting) {
  const page = await global_browser.newPage();
  await page.setViewport({
    width: 1000,
    height: 768
  });

  return await new Promise(async(resolve, reject) => {
      await page.$eval('#username', (el, setting) => el.value = setting.username, setting);
      await page.$eval('#password', (el, setting) => el.value = setting.password, setting);
      await Promise.all(
        page.$eval('form', form => form.submit()),
        page.waitForNavigation()
      )
      await page.goto('http://example.com/dashboard');
      resolve();
    }).then(() => {
      console.log(' -> don!  ');
      page.close();
    })
    .catch(() => {
      console.log(' -> somethign went wrong !');
      page.close();
    })
}

我明白了

(node:14812) UnhandledPromiseRejectionWarning: TypeError: undefined is not a function
    at Function.all (<anonymous>)
    at Promise (D:\wamp\www\gatewayCard\robot\server.js:287:23)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
(node:14812) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:14812) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

【问题讨论】:

  • 在使用 async...await 时使用 try...catch 而不是 new Promise 块。
  • 顺便说一句,您为什么不先访问网站就填写表格? XD
  • @Md.AbuTaher 我已经删除了额外的代码,比如去网站,所以我们可以专注于问题
  • @Md.AbuTaher mew Promise 被建议 https://stackoverflow.com/questions/52059034 这里因为我需要函数超时
  • 你可以了解更多关于 Promise.race :) ,从我所见,你绝对应该尝试研究这些,因为你最近的所有问题都非常相似,我很佩服你为所有人发布问题的勇气这些。

标签: javascript puppeteer


【解决方案1】:

发生这种情况是因为导航可能会在您等待之前在提交时发生。

在一个使用 Promise.all 的 Promise 中使用提交和 waitForNavigation,因此它会同时等待它们,而不是一次等待一个。

await Promise.all([
 page.waitForNavigation(),
 page.$eval('form', form => form.submit())
])

或者,

await Promise.all([
 page.$eval('form', form => form.submit()),
 page.waitForNavigation()
])

两者都应该工作。

编辑 1:

编辑与您的主要问题完全无关。您没有在代码中使用正确的 async...await 。这是一个更好的代码。

async...await 函数的美妙之处在于您可以编写更少的代码并提高可读性和可维护性。这是一把双刃剑,但如果使用得当,还是值得的。

async function open_tab(setting) {
  try {
    const page = await global_browser.newPage();
    await page.setViewport({
      width: 1000,
      height: 768
    });
    await page.goto('http://example.com/dashboard');
    await page.$eval('#username', (el, setting) => el.value = setting.username, setting);
    await page.$eval('#password', (el, setting) => el.value = setting.password, setting);
    await Promise.all(page.$eval('form', form => form.submit()), page.waitForNavigation());
    console.log(' -> don!  ');
    await page.close();
  } catch (error) {
    console.log(' -> somethign went wrong !', error);
    await page.close();
  }
}

编辑 2:

在您的代码中,

return await new Promise(async (resolve, reject ) => {

这在许多步骤上都是错误的。无论如何,异步函数都会返回一个 Promise,因此您在 Promise 中返回一个 Promise 而不捕获它并使用 await 。尽早检查你的代码,否则你很快就会面临巨大的问题。

看来你应该先了解更多关于 async await 的知识。这里有一些对您有用的链接,这些链接将解释超时以及您想了解的所有内容。

【讨论】:

  • 嗨,看起来合乎逻辑,但是当我更新我的代码时出现错误.. 请看看我的问题,我已经用错误更新了
  • 这一行是什么? (D:\wamp\www\gatewayCard\robot\server.js:287:23)
  • Promise.all 在那一行!
  • 我已经更新了我的代码,所以有更多的上下文......promise.all 在另一个promise 中所以也许这就是cuzing 错误
猜你喜欢
  • 1970-01-01
  • 2019-11-14
  • 1970-01-01
  • 1970-01-01
  • 2017-05-22
  • 2018-11-23
  • 2011-04-15
  • 2021-12-20
  • 2021-11-23
相关资源
最近更新 更多