将 await / async 与 Puppeter 函数一起使用时出错
Error using await / async with Puppeter functions
我正在尝试放置一系列我将在我的程序中重复多次的连续步骤,例如登录、在表单中搜索某些数据条件或结束会话。
这是我将 Puppeter 的步骤放在函数中的方式
login: function (page, selector){
(async () => {
await page.goto(“localhost:8080/login”);
await page.type(“#username”, “admin”);
console.log("STEP 1 USERNAME”);
await page.type(“#password”, “admin1”);
console.log("STEP 2 PASSWORD”);
await page.waitForSelector(“#submit”).then(() =>
page.click(“#submit”)
);
console.log("STEP 3 - Login");
})();
}
这是我的主要js程序(main.js
)
CASE1: function (req, res) {
(async () => {
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
console.log("STARTING CASE 1”);
await page.setViewport({ "width": 1280, "height": 720 });
login (page, selector);
await page.waitForSelector(“#combobox_of_day”).then(() =>
page.click(“#combobox_of_day”)
);
console.log("SELECT combobox of day”);
await page.waitForSelector(“#combobox_of_month”).then(() =>
page.click(“#combobox_of_month”)
);
console.log("SELECT combobox of month”);
await page.waitForSelector(“#combobox_of_year”).then(() =>
page.click(“#combobox_of_ year”)
);
console.log("SELECT combobox of year”);
await browser.close();
console.log("ENDING navigation”);
} catch (error) {
console.log(error);
}
})();
}
所以我希望在 NodeJS 控制台看到类似的东西
STARTING CASE 1
STEP 1 USERNAME
STEP 2 PASSWORD
STEP 3 Login
SELECT combobox of day
SELECT combobox of month
SELECT combobox of year
ENDING navigation
但是你在控制台上得到的是这样的
STARTING CASE 1
STEP 1 USERNAME
SELECT combobox of day
SELECT combobox of month
SELECT combobox of year
STEP 2 PASSWORD
STEP 3 Login
ENDING navigation
还有一条错误消息
{ TimeoutError: waiting for selector "#username" failed: timeout 30000ms exceeded
at new WaitTask (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\FrameManager.js:864:28)
at Frame._waitForSelectorOrXPath (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\FrameManager.js:755:12)
at Frame.waitForSelector (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\FrameManager.js:713:17)
at Page.waitForSelector (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\Page.js:1017:29)
at Z:\Documents\AR-puppeter\pruebas-app-ar\modulos\escenarios\escenario.js:145:28
at <anonymous> name: 'TimeoutError' }
因为问题似乎是调用函数“Login ()
”并没有停止连续行的执行。
如何让程序 (main.js
) 等待我的“Login ()
”函数的所有步骤继续?
使用async / await
和WaitForSelector
没有解决这个问题?
我在从我的程序 (main.js
) 调用“Login ()
”函数时尝试使用不同的语法,但我遇到了同样的错误。
async login (page, selector); //Getting same error
await login (page, selector); //Getting same error
您对 login
的表述很奇怪:您使用 IIFE 到 运行 async
函数,但由于包装器不是 async
,你永远不会等待承诺。你也不会在 CASE1
中等待 login
,但是你不能那样做,因为它没有 return 任何东西。你需要先把 login
return 变成 async
变成 Promise
(你可以 return 变成 Promise
而不是 async
, 但你将无法在其中使用 await
):
login: async (page, selector) => {
await page.goto("localhost:8080/login");
await page.type("#username", "admin");
console.log("STEP 1 USERNAME");
await page.type("#password", "admin1");
console.log("STEP 2 PASSWORD");
const submit = await page.waitForSelector("#submit");
await submit.click();
console.log("STEP 3 - Login");
}
waitForSelector
returns the ElementHandle
,所以不需要单独调用page.click
,也不需要在任何情况下使用then
。现在 login
return 是 Promise
.
接下来,您需要 await
CASE1
中的 Promise
并删除 IIFE 以支持函数本身 async
:
CASE1: async (req, res) => {
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
console.log("STARTING CASE 1");
await page.setViewport({ "width": 1280, "height": 720 });
await login(page, selector);
for (const type of ["day", "month", "year"]) {
const combobox = await page.waitForSelector(`#combobox_of_${type}`);
await combobox.click();
console.log(`SELECT combobox of ${type}`);
}
await browser.close();
console.log("ENDING navigation");
} catch (error) {
console.log(error);
}
}
我删除了一些重复的内容。似乎没有 selector
变量,这与 login
忽略它一样好,但我还是保留了它以匹配您的代码。
顺便说一句,避免使用文字处理器来处理代码。我不得不先花一些时间修复智能引号。
我正在尝试放置一系列我将在我的程序中重复多次的连续步骤,例如登录、在表单中搜索某些数据条件或结束会话。
这是我将 Puppeter 的步骤放在函数中的方式
login: function (page, selector){
(async () => {
await page.goto(“localhost:8080/login”);
await page.type(“#username”, “admin”);
console.log("STEP 1 USERNAME”);
await page.type(“#password”, “admin1”);
console.log("STEP 2 PASSWORD”);
await page.waitForSelector(“#submit”).then(() =>
page.click(“#submit”)
);
console.log("STEP 3 - Login");
})();
}
这是我的主要js程序(main.js
)
CASE1: function (req, res) {
(async () => {
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
console.log("STARTING CASE 1”);
await page.setViewport({ "width": 1280, "height": 720 });
login (page, selector);
await page.waitForSelector(“#combobox_of_day”).then(() =>
page.click(“#combobox_of_day”)
);
console.log("SELECT combobox of day”);
await page.waitForSelector(“#combobox_of_month”).then(() =>
page.click(“#combobox_of_month”)
);
console.log("SELECT combobox of month”);
await page.waitForSelector(“#combobox_of_year”).then(() =>
page.click(“#combobox_of_ year”)
);
console.log("SELECT combobox of year”);
await browser.close();
console.log("ENDING navigation”);
} catch (error) {
console.log(error);
}
})();
}
所以我希望在 NodeJS 控制台看到类似的东西
STARTING CASE 1
STEP 1 USERNAME
STEP 2 PASSWORD
STEP 3 Login
SELECT combobox of day
SELECT combobox of month
SELECT combobox of year
ENDING navigation
但是你在控制台上得到的是这样的
STARTING CASE 1
STEP 1 USERNAME
SELECT combobox of day
SELECT combobox of month
SELECT combobox of year
STEP 2 PASSWORD
STEP 3 Login
ENDING navigation
还有一条错误消息
{ TimeoutError: waiting for selector "#username" failed: timeout 30000ms exceeded
at new WaitTask (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\FrameManager.js:864:28)
at Frame._waitForSelectorOrXPath (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\FrameManager.js:755:12)
at Frame.waitForSelector (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\FrameManager.js:713:17)
at Page.waitForSelector (Z:\Documents\AR-puppeter\node_modules\puppeteer\lib\Page.js:1017:29)
at Z:\Documents\AR-puppeter\pruebas-app-ar\modulos\escenarios\escenario.js:145:28
at <anonymous> name: 'TimeoutError' }
因为问题似乎是调用函数“Login ()
”并没有停止连续行的执行。
如何让程序 (main.js
) 等待我的“Login ()
”函数的所有步骤继续?
使用async / await
和WaitForSelector
没有解决这个问题?
我在从我的程序 (main.js
) 调用“Login ()
”函数时尝试使用不同的语法,但我遇到了同样的错误。
async login (page, selector); //Getting same error
await login (page, selector); //Getting same error
您对 login
的表述很奇怪:您使用 IIFE 到 运行 async
函数,但由于包装器不是 async
,你永远不会等待承诺。你也不会在 CASE1
中等待 login
,但是你不能那样做,因为它没有 return 任何东西。你需要先把 login
return 变成 async
变成 Promise
(你可以 return 变成 Promise
而不是 async
, 但你将无法在其中使用 await
):
login: async (page, selector) => {
await page.goto("localhost:8080/login");
await page.type("#username", "admin");
console.log("STEP 1 USERNAME");
await page.type("#password", "admin1");
console.log("STEP 2 PASSWORD");
const submit = await page.waitForSelector("#submit");
await submit.click();
console.log("STEP 3 - Login");
}
waitForSelector
returns the ElementHandle
,所以不需要单独调用page.click
,也不需要在任何情况下使用then
。现在 login
return 是 Promise
.
接下来,您需要 await
CASE1
中的 Promise
并删除 IIFE 以支持函数本身 async
:
CASE1: async (req, res) => {
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
console.log("STARTING CASE 1");
await page.setViewport({ "width": 1280, "height": 720 });
await login(page, selector);
for (const type of ["day", "month", "year"]) {
const combobox = await page.waitForSelector(`#combobox_of_${type}`);
await combobox.click();
console.log(`SELECT combobox of ${type}`);
}
await browser.close();
console.log("ENDING navigation");
} catch (error) {
console.log(error);
}
}
我删除了一些重复的内容。似乎没有 selector
变量,这与 login
忽略它一样好,但我还是保留了它以匹配您的代码。
顺便说一句,避免使用文字处理器来处理代码。我不得不先花一些时间修复智能引号。