Javascript循环、异步函数和无头浏览器

Javascript循环、异步函数和无头浏览器,javascript,node.js,puppeteer,playwright,Javascript,Node.js,Puppeteer,Playwright,通过与微软新的无头浏览器剧作家合作,我创造了一个既不返回错误也不返回其他错误的东西 现在,我的想法结束了,我请求你给我一些提示,指出我的失败 这段代码应该只是启动一个多无头浏览器组异步。 但是,浏览器的启动挂起,应用程序处于一个无休止的循环中。 我将代码粘贴到这里,这是一个简单的nodejs脚本,用于重现行为 感谢您的帮助&reading;) 我不相信您的异步函数实际上正在被评估 您可以创建一个承诺列表并使用它,而不是每次迭代调用一次异步函数吗?立即调用的函数将在不等待完成的情况下执行。例如:

通过与微软新的无头浏览器剧作家合作,我创造了一个既不返回错误也不返回其他错误的东西

现在,我的想法结束了,我请求你给我一些提示,指出我的失败

这段代码应该只是启动一个多无头浏览器组异步。 但是,浏览器的启动挂起,应用程序处于一个无休止的循环中。 我将代码粘贴到这里,这是一个简单的nodejs脚本,用于重现行为

感谢您的帮助&reading;)


我不相信您的异步函数实际上正在被评估


您可以创建一个承诺列表并使用它,而不是每次迭代调用一次异步函数吗?

立即调用的函数将在不等待完成的情况下执行。例如:

const promise=(time=1,shouldThrowerr=false)=>新承诺((解析,拒绝)=>{
timeInMs=时间*1000
设置超时(()=>{
log(`Waited${time}secs`)
如果(shouldThrowerr)拒绝(新错误(“承诺失败”))
解决(时间)
},timeInMs)
});
//开始执行第一个异步立即数函数
(异步()=>{
试一试{
console.log('启动第一个承诺')
等待承诺(1)
console.log('finished first promise')
}捕获(错误){
}
})();
//这在没有完成之前的承诺的情况下执行
(异步()=>{
试一试{
console.log('启动第二个承诺')
等待承诺(1)
console.log('finished second promise')
}捕获(错误){
}

})();您可以在代码中改进以下几点:

(异步()=>{
日志(“开始编剧异步”);
设maxRunners=1;
让running=0;
let list=[1,2,3,4,5,6,7,8,9,0,11,12,13,14,15];
日志(“启动作业”);
常量承诺=[];
while(list.length>0){
如果(运行<最大运行){
日志(“运行程序已启动”);
运行++;
let entry=list[0];
list.shift();
日志(“启动浏览器循环”);
用于(常量浏览器类型['chromium'、'firefox'、'webkit']){
日志('fire async');
promises.push((异步()=>{
日志(“循环下一步”);
日志('启动:',浏览器类型);
const browser=等待剧作家[browserType]。启动({
无头:错
});
日志(browserType,“已启动”);
const context=await browser.newContext();
日志(“打开新页面”);
const page=await context.newPage('http://whatsmyuseragent.org/');
日志(“打开的页面”);
日志(“制作屏幕截图”);
等待page.screenshot({path:`example-${browserType}.png`});
日志(“截图制作”);
日志(“关闭浏览器”);
等待浏览器关闭();
日志(“浏览器关闭”);
日志(“循环成功”);
运行--;
})());
日志('end async');
}
日志(“结束循环”);
}否则{
等待承诺。所有(承诺);
}
}
等待承诺。所有(承诺);
日志(“作业已完成”);
日志(“编剧剧本结尾”);
函数日志(…msgs){
让日期=新日期();
让timeString=date.toISOString().substr(11,8);
//date.setSeconds(45);//在此处指定秒的值
//var timeString=date.toISOString().substr(11,8);
让msg='';
用于(让我输入MSG){
msg+=msgs[i];
}
log(时间字符串“:”,msg);
}
})()
让我们将所有内容包装在一个异步函数中

(异步()=>{
)();
然后,让我们跟踪这些任务/承诺:

const promises=[];
...
日志('fire async');
promises.push((异步()=>{
})());
如果你离开了工人,你需要等待他们:

if(运行

根据@hardkoded的优秀答案,您应该在同一行上运行此命令。

简而言之,使用带有承诺的异步函数:

一个简单说明相同观点的基本示例:

function delay() {
  return new Promise(resolve => setTimeout(resolve, 300));
}

async function delayedLog(item) {
  // notice that we can await a function
  // that returns a promise
  await delay();
  console.log(item);
}



async function processArray(array) {
  // map array to promises
  const promises = array.map(delayedLog);
  // wait until all promises are resolved
  await Promise.all(promises);
  console.log('Done!');
}

尝试它,玩它来理解javaScript中的异步行为!

调试器在循环内停止,然后进入浏览器。这只是一个示例,实际代码执行一个函数,并承诺启动浏览器。添加输出后,您可以看到异步函数被评估,并在启动时停止。感谢您的有用提示。更好的o一直等待承诺而不是执行条件。现在我也在所有完成后清除承诺数组。
20:53:29 : start playwright async
20:53:29 : start job
20:53:29 : runner started
20:53:29 : start browser loop
20:53:29 : fire async
20:53:29 : loop next
20:53:29 : launch: chromium
20:53:29 : end async
20:53:29 : fire async
20:53:29 : loop next
20:53:29 : launch: firefox
20:53:29 : end async
20:53:29 : fire async
20:53:29 : loop next
20:53:29 : launch: webkit
20:53:29 : end async
20:53:29 : end loop
function delay() {
  return new Promise(resolve => setTimeout(resolve, 300));
}

async function delayedLog(item) {
  // notice that we can await a function
  // that returns a promise
  await delay();
  console.log(item);
}



async function processArray(array) {
  // map array to promises
  const promises = array.map(delayedLog);
  // wait until all promises are resolved
  await Promise.all(promises);
  console.log('Done!');
}