在 Puppeteer 中使用 page.waitForNavigation 的正确方法
Proper way to use page.waitForNavigation in Puppeteer
我对 page.waitForNavigation
有点困惑。我知道它是什么以及它的作用,但我根据互联网速度得到不同的结果(这就是我认为的因素)。
想象一下这段代码:
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' );
它填写登录表单,提交登录表单,等待表单提交,然后重定向到仪表板。
这在网速较慢的本地主机上运行良好(与服务器相比),但是当我将其上传到服务器时,我得到
Error: Navigation Timeout Exceeded: 30000ms exceeded
在服务器上,如果我从代码中删除 await page.waitForNavigation();
并且我被重定向到仪表板,它工作正常。
但现在在本地主机上,我在提交表单之前被重定向到仪表板。我得到 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.
发生这种情况是因为导航可能在您等待之前提交时发生。
使用 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 ) => {
这在很多步骤上都是错误的。 async functions returns 一个 promise 无论如何,所以你在一个 promise 中返回一个 promise 而不捕获它并使用 await 。早点检查你的代码,否则你很快就会遇到大问题。
看来你应该先多了解一下 async await。这里有一些对您有用的链接,这些链接将解释超时和您想了解的所有内容。
我对 page.waitForNavigation
有点困惑。我知道它是什么以及它的作用,但我根据互联网速度得到不同的结果(这就是我认为的因素)。
想象一下这段代码:
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' );
它填写登录表单,提交登录表单,等待表单提交,然后重定向到仪表板。
这在网速较慢的本地主机上运行良好(与服务器相比),但是当我将其上传到服务器时,我得到
Error: Navigation Timeout Exceeded: 30000ms exceeded
在服务器上,如果我从代码中删除 await page.waitForNavigation();
并且我被重定向到仪表板,它工作正常。
但现在在本地主机上,我在提交表单之前被重定向到仪表板。我得到 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.
发生这种情况是因为导航可能在您等待之前提交时发生。
使用 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 ) => {
这在很多步骤上都是错误的。 async functions returns 一个 promise 无论如何,所以你在一个 promise 中返回一个 promise 而不捕获它并使用 await 。早点检查你的代码,否则你很快就会遇到大问题。
看来你应该先多了解一下 async await。这里有一些对您有用的链接,这些链接将解释超时和您想了解的所有内容。