Puppeteer wait until page is completely loaded

后端 未结 7 1232
梦如初夏
梦如初夏 2020-12-01 06:40

I am working on creating PDF from web page.

The application on which I am working is single page application.

I tried many options and suggestion on https://

相关标签:
7条回答
  • 2020-12-01 06:44

    In some cases, the best solution for me was:

    await page.goto(url, { waitUntil: 'domcontentloaded' });
    

    Some other options you could try are:

    await page.goto(url, { waitUntil: 'load' });
    await page.goto(url, { waitUntil: 'domcontentloaded' });
    await page.goto(url, { waitUntil: 'networkidle0' });
    await page.goto(url, { waitUntil: 'networkidle2' });
    

    You can check this at puppeteer documentation: https://pptr.dev/#?product=Puppeteer&version=v2.1.1&show=api-pagewaitfornavigationoptions

    0 讨论(0)
  • 2020-12-01 06:50

    Wrap the page.click and page.waitForNavigation in a Promise.all

      await Promise.all([
        page.click('#submit_button'),
        page.waitForNavigation({ waitUntil: 'networkidle0' })
      ]);
    
    0 讨论(0)
  • 2020-12-01 06:54

    I always like to wait for selectors, as many of them are a great indicator that the page has fully loaded:

    await page.waitForSelector('#blue-button');
    
    0 讨论(0)
  • 2020-12-01 06:54

    In the latest Puppeteer version, networkidle2 worked for me:

    await page.goto(url, { waitUntil: 'networkidle2' });
    
    0 讨论(0)
  • 2020-12-01 06:57

    Sometimes the networkidle events do not always give an indication that the page has completely loaded. There could still be a few JS scripts modifying the content on the page. So watching for the completion of HTML source code modifications by the browser seems to be yielding better results. Here's a function you could use -

    const waitTillHTMLRendered = async (page, timeout = 30000) => {
      const checkDurationMsecs = 1000;
      const maxChecks = timeout / checkDurationMsecs;
      let lastHTMLSize = 0;
      let checkCounts = 1;
      let countStableSizeIterations = 0;
      const minStableSizeIterations = 3;
    
      while(checkCounts++ <= maxChecks){
        let html = await page.content();
        let currentHTMLSize = html.length; 
    
        let bodyHTMLSize = await page.evaluate(() => document.body.innerHTML.length);
    
        console.log('last: ', lastHTMLSize, ' <> curr: ', currentHTMLSize, " body html size: ", bodyHTMLSize);
    
        if(lastHTMLSize != 0 && currentHTMLSize == lastHTMLSize) 
          countStableSizeIterations++;
        else 
          countStableSizeIterations = 0; //reset the counter
    
        if(countStableSizeIterations >= minStableSizeIterations) {
          console.log("Page rendered fully..");
          break;
        }
    
        lastHTMLSize = currentHTMLSize;
        await page.waitFor(checkDurationMsecs);
      }  
    };
    

    You could use this after the page load / click function call and before you process the page content. e.g.

    await page.goto(url, {'timeout': 10000, 'waitUntil':'load'});
    await waitTillHTMLRendered(page)
    const data = await page.content()
    
    0 讨论(0)
  • 2020-12-01 07:02

    You can use page.waitForNavigation() to wait for the new page to load completely before generating a PDF:

    await page.goto(fullUrl, {
      waitUntil: 'networkidle0',
    });
    
    await page.type('#username', 'scott');
    await page.type('#password', 'tiger');
    
    await page.click('#Login_Button');
    
    await page.waitForNavigation({
      waitUntil: 'networkidle0',
    });
    
    await page.pdf({
      path: outputFileName,
      displayHeaderFooter: true,
      headerTemplate: '',
      footerTemplate: '',
      printBackground: true,
      format: 'A4',
    });
    

    If there is a certain element that is generated dynamically that you would like included in your PDF, consider using page.waitForSelector() to ensure that the content is visible:

    await page.waitForSelector('#example', {
      visible: true,
    });
    
    0 讨论(0)
提交回复
热议问题