我的同步功能在哪里?尝试调用 "await" 但出现错误 "await is only valid in async function."
Where is my synchronous function? Trying to call "await" but I get the error "await is only valid in async function."
尝试编写一个使用 puppeteer 登录网站的脚本,并在设备通过每个 url 时模拟设备列表。但是,当我尝试 运行 脚本时出现错误:SyntaxError: await is only valid in async function
。我对异步函数不是很熟悉所以我试图让每个函数都异步,但我找不到我的同步函数。如果是当我映射每个 url 时,我如何使它同步?
//import devices from './puppeteerDevices'
const puppeteer = require('puppeteer');
const { devices } = puppeteer;
testedMobileDevices = ["Galaxy Note 3","Galaxy Note 3 landscape","Galaxy Note II","Galaxy Note II landscape","Galaxy S III","Galaxy S III landscape","Galaxy S5","Galaxy S5 landscape","iPad","iPad landscape","iPad Mini","iPad Mini landscape","iPad Pro","iPad Pro landscape","iPhone 4","iPhone 4 landscape","iPhone 5","iPhone 5 landscape","iPhone 6","iPhone 6 landscape","iPhone 6 Plus","iPhone 6 Plus landscape","iPhone 7","iPhone 7 landscape","iPhone 7 Plus","iPhone 7 Plus landscape","iPhone 8","iPhone 8 landscape","iPhone 8 Plus","iPhone 8 Plus landscape","iPhone SE","iPhone SE landscape","iPhone X","iPhone X landscape","iPhone XR","iPhone XR landscape","iPhone 11","iPhone 11 landscape","iPhone 11 Pro","iPhone 11 Pro landscape","iPhone 11 Pro Max","iPhone 11 Pro Max landscape","Nexus 10","Nexus 10 landscape","Nexus 4","Nexus 4 landscape","Nexus 5","Nexus 5 landscape","Nexus 5X","Nexus 5X landscape","Nexus 6","Nexus 6 landscape","Nexus 6P","Nexus 6P landscape","Nexus 7","Nexus 7 landscape","Pixel 2","Pixel 2 landscape","Pixel 2 XL","Pixel 2 XL landscape"];
const login = async () => {
const browser = await puppeteer.launch( {headless: true });
const page = await browser.newPage();
const username = 'andrewbregman'
const password = 'randompassword120948acndkla'
const base_url = 'http://127.0.0.1:8000/'
await page.goto({base_url}/login);
await page.type ('[name=username]', username);
await page.type('[name=password]', password);
await page.click('[type=submit]');
await page.waitFor(5000);
}
const test = async () => {
testedMobileDevices.map(device => {
login();
const base_url = 'http://127.0.0.1:8000/'
const urls = ['myprojects', 'home', 'notifications']
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.emulate(device)
urls.forEach(goUrls);
const goUrls = async (url) =>{
await page.goto({base_url}/url)
page.screenshot({
path: "./screenshot.jpg",
type: "jpeg",
fullPage: true})
await page.waitFor(100);
}
})
}
test();
您需要创建传递给 testedMobileDevices.map
的函数 async
:
const test = async () => {
testedMobileDevices.map(async(device) => {
login();
const base_url = 'http://127.0.0.1:8000/'
const urls = ['myprojects', 'home', 'notifications']
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.emulate(device)
urls.forEach(goUrls);
const goUrls = async (url) =>{
await page.goto({base_url}/url)
page.screenshot({
path: "./screenshot.jpg",
type: "jpeg",
fullPage: true})
await page.waitFor(100);
}
})}
看来您应该一次对这些进行排序,否则您可能会有大量无头 chrome 浏览器同时竞争本地资源。因此,总而言之,您需要进行以下更改:
- 将操作一个接一个地排序,以避免并行使用太多资源。
- 正确地向调用方反馈完成或错误。
- 正确声明了字符串模板。
- 对所有承诺返回操作使用
await
。
- 删除所有对
.forEach()
的使用,因为它不是 promise-aware 和 .map()
,因为你真的不想 运行 所有 100 个左右并行。将其替换为常规 for
循环,该循环继承了父级的 async
声明并且具有 promise 意识并且易于排序。
- 当您调用它时,记录完成并捕获并记录任何错误。
- 如编码所示,这将在第一次出错时中止。您可以修改代码以捕获任何错误、记录它、清除该错误并在下一次迭代中继续循环。在继续之前,您需要在几个地方使用
try/catch
并在 catch
块中使用正确的代码进行清理。
仅供参考,这是您环境中的代码,因此这代表了您应该瞄准的结构 - 您可能需要修复其他编码错误(因为我已经注意到模板字符串声明的编码错误 - 可能成为其他人)。
以下是完成所有这些操作的方法:
//import devices from './puppeteerDevices'
const puppeteer = require('puppeteer');
const { devices } = puppeteer;
const testedMobileDevices = ["Galaxy Note 3", "Galaxy Note 3 landscape", "Galaxy Note II", "Galaxy Note II landscape",
"Galaxy S III", "Galaxy S III landscape", "Galaxy S5", "Galaxy S5 landscape", "iPad", "iPad landscape",
"iPad Mini", "iPad Mini landscape", "iPad Pro", "iPad Pro landscape", "iPhone 4", "iPhone 4 landscape",
"iPhone 5", "iPhone 5 landscape", "iPhone 6", "iPhone 6 landscape", "iPhone 6 Plus", "iPhone 6 Plus landscape",
"iPhone 7", "iPhone 7 landscape", "iPhone 7 Plus", "iPhone 7 Plus landscape", "iPhone 8", "iPhone 8 landscape",
"iPhone 8 Plus", "iPhone 8 Plus landscape", "iPhone SE", "iPhone SE landscape", "iPhone X",
"iPhone X landscape", "iPhone XR", "iPhone XR landscape", "iPhone 11", "iPhone 11 landscape", "iPhone 11 Pro",
"iPhone 11 Pro landscape", "iPhone 11 Pro Max", "iPhone 11 Pro Max landscape", "Nexus 10", "Nexus 10 landscape",
"Nexus 4", "Nexus 4 landscape", "Nexus 5", "Nexus 5 landscape", "Nexus 5X", "Nexus 5X landscape", "Nexus 6",
"Nexus 6 landscape", "Nexus 6P", "Nexus 6P landscape", "Nexus 7", "Nexus 7 landscape", "Pixel 2",
"Pixel 2 landscape", "Pixel 2 XL", "Pixel 2 XL landscape"
];
async function login() {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
const username = 'andrewbregman';
const password = 'randompassword120948acndkla';
const base_url = 'http://127.0.0.1:8000/';
await page.goto(`${base_url}/login`);
await page.type('[name=username]', username);
await page.type('[name=password]', password);
await page.click('[type=submit]');
await page.waitFor(5000);
}
async function test() {
for (let device of testedMobileDevices) {
await login();
const base_url = 'http://127.0.0.1:8000/'
const urls = ['myprojects', 'home', 'notifications']
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.emulate(device);
for (let url or urls) {
await page.goto(`${ base_url }/url`);
await page.screenshot({
path: "./screenshot.jpg",
type: "jpeg",
fullPage: true
});
await page.waitFor(100);
}
}
}
test().then(() => {
console.log("all done");
}).catch(err => {
console.log(err);
});
尝试编写一个使用 puppeteer 登录网站的脚本,并在设备通过每个 url 时模拟设备列表。但是,当我尝试 运行 脚本时出现错误:SyntaxError: await is only valid in async function
。我对异步函数不是很熟悉所以我试图让每个函数都异步,但我找不到我的同步函数。如果是当我映射每个 url 时,我如何使它同步?
//import devices from './puppeteerDevices'
const puppeteer = require('puppeteer');
const { devices } = puppeteer;
testedMobileDevices = ["Galaxy Note 3","Galaxy Note 3 landscape","Galaxy Note II","Galaxy Note II landscape","Galaxy S III","Galaxy S III landscape","Galaxy S5","Galaxy S5 landscape","iPad","iPad landscape","iPad Mini","iPad Mini landscape","iPad Pro","iPad Pro landscape","iPhone 4","iPhone 4 landscape","iPhone 5","iPhone 5 landscape","iPhone 6","iPhone 6 landscape","iPhone 6 Plus","iPhone 6 Plus landscape","iPhone 7","iPhone 7 landscape","iPhone 7 Plus","iPhone 7 Plus landscape","iPhone 8","iPhone 8 landscape","iPhone 8 Plus","iPhone 8 Plus landscape","iPhone SE","iPhone SE landscape","iPhone X","iPhone X landscape","iPhone XR","iPhone XR landscape","iPhone 11","iPhone 11 landscape","iPhone 11 Pro","iPhone 11 Pro landscape","iPhone 11 Pro Max","iPhone 11 Pro Max landscape","Nexus 10","Nexus 10 landscape","Nexus 4","Nexus 4 landscape","Nexus 5","Nexus 5 landscape","Nexus 5X","Nexus 5X landscape","Nexus 6","Nexus 6 landscape","Nexus 6P","Nexus 6P landscape","Nexus 7","Nexus 7 landscape","Pixel 2","Pixel 2 landscape","Pixel 2 XL","Pixel 2 XL landscape"];
const login = async () => {
const browser = await puppeteer.launch( {headless: true });
const page = await browser.newPage();
const username = 'andrewbregman'
const password = 'randompassword120948acndkla'
const base_url = 'http://127.0.0.1:8000/'
await page.goto({base_url}/login);
await page.type ('[name=username]', username);
await page.type('[name=password]', password);
await page.click('[type=submit]');
await page.waitFor(5000);
}
const test = async () => {
testedMobileDevices.map(device => {
login();
const base_url = 'http://127.0.0.1:8000/'
const urls = ['myprojects', 'home', 'notifications']
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.emulate(device)
urls.forEach(goUrls);
const goUrls = async (url) =>{
await page.goto({base_url}/url)
page.screenshot({
path: "./screenshot.jpg",
type: "jpeg",
fullPage: true})
await page.waitFor(100);
}
})
}
test();
您需要创建传递给 testedMobileDevices.map
的函数 async
:
const test = async () => {
testedMobileDevices.map(async(device) => {
login();
const base_url = 'http://127.0.0.1:8000/'
const urls = ['myprojects', 'home', 'notifications']
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.emulate(device)
urls.forEach(goUrls);
const goUrls = async (url) =>{
await page.goto({base_url}/url)
page.screenshot({
path: "./screenshot.jpg",
type: "jpeg",
fullPage: true})
await page.waitFor(100);
}
})}
看来您应该一次对这些进行排序,否则您可能会有大量无头 chrome 浏览器同时竞争本地资源。因此,总而言之,您需要进行以下更改:
- 将操作一个接一个地排序,以避免并行使用太多资源。
- 正确地向调用方反馈完成或错误。
- 正确声明了字符串模板。
- 对所有承诺返回操作使用
await
。 - 删除所有对
.forEach()
的使用,因为它不是 promise-aware 和.map()
,因为你真的不想 运行 所有 100 个左右并行。将其替换为常规for
循环,该循环继承了父级的async
声明并且具有 promise 意识并且易于排序。 - 当您调用它时,记录完成并捕获并记录任何错误。
- 如编码所示,这将在第一次出错时中止。您可以修改代码以捕获任何错误、记录它、清除该错误并在下一次迭代中继续循环。在继续之前,您需要在几个地方使用
try/catch
并在catch
块中使用正确的代码进行清理。
仅供参考,这是您环境中的代码,因此这代表了您应该瞄准的结构 - 您可能需要修复其他编码错误(因为我已经注意到模板字符串声明的编码错误 - 可能成为其他人)。
以下是完成所有这些操作的方法:
//import devices from './puppeteerDevices'
const puppeteer = require('puppeteer');
const { devices } = puppeteer;
const testedMobileDevices = ["Galaxy Note 3", "Galaxy Note 3 landscape", "Galaxy Note II", "Galaxy Note II landscape",
"Galaxy S III", "Galaxy S III landscape", "Galaxy S5", "Galaxy S5 landscape", "iPad", "iPad landscape",
"iPad Mini", "iPad Mini landscape", "iPad Pro", "iPad Pro landscape", "iPhone 4", "iPhone 4 landscape",
"iPhone 5", "iPhone 5 landscape", "iPhone 6", "iPhone 6 landscape", "iPhone 6 Plus", "iPhone 6 Plus landscape",
"iPhone 7", "iPhone 7 landscape", "iPhone 7 Plus", "iPhone 7 Plus landscape", "iPhone 8", "iPhone 8 landscape",
"iPhone 8 Plus", "iPhone 8 Plus landscape", "iPhone SE", "iPhone SE landscape", "iPhone X",
"iPhone X landscape", "iPhone XR", "iPhone XR landscape", "iPhone 11", "iPhone 11 landscape", "iPhone 11 Pro",
"iPhone 11 Pro landscape", "iPhone 11 Pro Max", "iPhone 11 Pro Max landscape", "Nexus 10", "Nexus 10 landscape",
"Nexus 4", "Nexus 4 landscape", "Nexus 5", "Nexus 5 landscape", "Nexus 5X", "Nexus 5X landscape", "Nexus 6",
"Nexus 6 landscape", "Nexus 6P", "Nexus 6P landscape", "Nexus 7", "Nexus 7 landscape", "Pixel 2",
"Pixel 2 landscape", "Pixel 2 XL", "Pixel 2 XL landscape"
];
async function login() {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
const username = 'andrewbregman';
const password = 'randompassword120948acndkla';
const base_url = 'http://127.0.0.1:8000/';
await page.goto(`${base_url}/login`);
await page.type('[name=username]', username);
await page.type('[name=password]', password);
await page.click('[type=submit]');
await page.waitFor(5000);
}
async function test() {
for (let device of testedMobileDevices) {
await login();
const base_url = 'http://127.0.0.1:8000/'
const urls = ['myprojects', 'home', 'notifications']
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.emulate(device);
for (let url or urls) {
await page.goto(`${ base_url }/url`);
await page.screenshot({
path: "./screenshot.jpg",
type: "jpeg",
fullPage: true
});
await page.waitFor(100);
}
}
}
test().then(() => {
console.log("all done");
}).catch(err => {
console.log(err);
});