nodejs 中的 map 函数 vs for loop puppeteer 包

map function vs for loop puppeteer package in nodejs

我一直在尝试 nodejs 中的 puppetter 包,当我使用数据函数时,它的工作方式与 for 循环相比有很大不同

我说的是:

地图函数

data.map(async(info) =>{
        let browser = await puppeteer.launch({ ignoreHTTPSErrors: true });
        let page = await browser.newPage();
        await page.goto(info.url, { waitUntil: "networkidle2" })
        await page.screenshot({ path: info.src })

        
        await browser.close();

    })

    console.log("map function completed");

这是地图函数的输入:

地图功能完成

第一张截图已保存

已保存第二个屏幕截图

For 循环是这样工作的:

let browser = await puppeteer.launch({ ignoreHTTPSErrors: true });
let page = await browser.newPage();

for (let i = 0; i<=data.length-1; i++) {
console.log(data[i].url);
await page.goto(data[i].url, { waitUntil: "networkidle2" })
await page.screenshot({ path: data[i].src })

}
await browser.close();
console.log("for loop completed");

这是for循环的输入:

第一张截图已保存

已保存第二个屏幕截图

for循环完成

为什么会这样?我以为他们以同样的方式工作。我希望有人解释这是为什么。

在第一种情况下,因为您在 map 函数中使用异步函数,所以第一个同步 console.log() 函数起作用。因为通常异步操作在同步操作之后工作。

在第二种情况下,for loop、top-level await 和 console.log() 函数按顺序工作,因为它们是同步的。

如果你想让它以同样的方式工作,你必须以这种方式更改你的第一个代码

const promises = data.map(async(info) =>{
        let browser = await puppeteer.launch({ ignoreHTTPSErrors: true });
        let page = await browser.newPage();
        await page.goto(info.url, { waitUntil: "networkidle2" })
        await page.screenshot({ path: info.src })

        
        await browser.close();

    })

await Promise.all(promises)
console.log("map function completed");

当您使用 mapasync 时,您的项目将转换为承诺并且它们将并行执行(在您的情况下这不是真的,因为您正在使用 puppeteer)所以您必须 await 所有这些都已解决以记录成功消息。

你的第二个代码更同步,因为它都是同一个函数的包装器,每个 await 一个接一个地执行