forEach循环中使用async,await关键字获取到的值总是最后一个?

   allUrls.forEach(async (item,index)=>{
        await page.goto(item.url);
        let imgUrls = await page.evaluate(e=>{
            let imgs = Array.from($('#picture').find("img"))
            return imgUrls = imgs.map((item)=>{
                let imgUrl = $(item).attr('src');
                let imgAlt = $(item).attr('alt');
                return {
                    imgUrl,imgAlt
                }
            })
        });
        allImgUrls = [...allImgUrls,...imgUrls];
        
    });

allImgUrls,allUrls,imgUrls都是数组,循环allUrls根据每一项得到一个数组imgUrls然后整合进allImgUrls里面,但最终结果imgUrls都是allUrls最后一项得到的结果?
求大神解答

阅读 6.5k
2 个回答

注明下这个是puppeteer吧...
forEach是并发的,所以你的page还没有等前一个页面操作完(甚至还没有打开前面的页面)就跳到下一个页面了。等执行获取图片属性的操作时,page已经进入了最后一个页面...
你需要使用for:

for(let index=0;index<allUrls.length;index++){
    let item=allUrls[index];
    await page.goto(item.url);
    let imgUrls = await page.evaluate(e=>{
        let imgs = Array.from($('#picture').find("img"))
        return imgUrls = imgs.map((item)=>{
            let imgUrl = $(item).attr('src');
            let imgAlt = $(item).attr('alt');
            return {
                imgUrl,imgAlt
            }
        })
    });
    allImgUrls = [...allImgUrls,...imgUrls];

}

如果你确实是要并发的话,就不能用一个page,而是要let newPage=await browser.newPage(url);,forEach就会一次性打开多个新页面了。可能会由于短时间请求过多被服务器拒绝,可以加上await sleep(index*5000),这样两个页面间打开的时间都会相差5s。

for(let x of ar){...} 中使用 async/await

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题