Puppeteer在所有iframe加载之前创建PDF

时间:2019-06-26 15:39:05

标签: node.js iframe puppeteer

我需要为包含约20个iframe并显示一些图表的网页创建PDF。显然,我需要等待所有iframe加载完毕。为此,我尝试了以下操作(摘要):

const browser = await puppeteer.launch({ args: ['--no-sandbox'] })
const page = await browser.newPage()

const navigationPromise = page.waitForNavigation({waitUntil: 'networkidle0'})
await page.goto(url)  
await navigationPromise

const pdf = await page.pdf()
await browser.close()

我的理解是,waitUntil: 'networkidle0'选项应该等待直到500毫秒内完全没有网络流量。但是,iframe并不总是显示,有些是,有些则没有。

我也尝试了networkidle2,但没有任何改善(这应该适用于长期运行的网络连接,而我们并不这样)。

还有什么其他方法可以确保所有iframe都已加载?

1 个答案:

答案 0 :(得分:2)

通常,loadnetworkidle*事件应在框架加载后触发。但是,如果在解析page.waitForNavigation之后将框架附加到页面上,则可能需要专门侦听要加载的框架。

存在framenavigated事件,该事件“在将框架导航到新的url时发出”。如果您知道需要收听的帧数,则只需等待所有帧加载完毕,就可以像这样:

const EXPECTED_NUMBER_OF_FRAMES = 5;
await Promise.all([
    new Promise(resolve => { // wait until all frames are navigated
        let numberOfLoadedFrames = 0;
        page.on('framenavigated', () => {
            numberOfLoadedFrames += 1;
            if (numberOfLoadedFrames === (EXPECTED_NUMBER_OF_FRAMES + 1)) {
                resolve();
            }
        });
    }),
    page.goto('...')
]);

当达到预期数量时,代码将监听framenavigated事件调用的数量和resolve的承诺。请记住,主机也会触发一次framenavigated事件,因此会触发我的代码中的EXPECTED_NUMBER_OF_FRAMES + 1

根据页面的复杂程度,您还可以侦听frameattached事件的发出数量,这些事件将表示页面中有多少帧。这样,您可以自动检测页面中有多少帧。但是,在这种情况下,您应该首先等待几毫秒,以确保捕获所有帧。