如何使用Express和Puppeteer为每个动态加载的页面拍摄屏幕截图?

时间:2019-10-17 17:56:40

标签: node.js express asynchronous puppeteer

我正在创建一个应用,我想在其中生成QR代码的图片以及其他一些文本内容,这些内容将动态生成[使用qrcode库]。借助PugJS模板和ExpressJS将QR代码呈现到端点。我必须存储此渲染屏幕的图片,这是我使用Puppeteer所做的。当生成一个 QR码并拍摄快照,或为单个QR码拍摄多个快照时,此方法就可以很好地工作。我要寻找的是生成一个QR码,对其进行快照,然后生成下一个QR码,对其进行快照,等等。

我所面临的问题是,由于Puppeteer驱动程序功能本质上是异步的,因此我认为可以拍摄多个屏幕截图的唯一方法是将其放入for循环中,然后像代码中给出的那样执行下面。但这不适用于较大的i(= 100)值,因为每次i迭代时,我们实际上都是在创建无头的chrome,并产生以下错误:

   (node:34536) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 exit listeners added. Use emitter.setMaxListeners() to limit
   (node:34536) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGINT listeners added. Use emitter.setMaxListeners() to increase limit

我尝试将for循环放在“ get”表达方法之后,在进行渲染以减少内存负载之前,我尝试更改异步代码中的执行流程。

   const express = require('express');
   const JsBarcode = require('jsbarcode');
   const { Canvas } = require("canvas");
   const app = express();
   const port = process.env.PORT || 3000;
   const QRCode = require('qrcode')
   const puppeteer = require('puppeteer');
   app.set('view engine', 'pug');
   app.use(express.static(__dirname + '/public'));

var renderdeet;

for (let i = 0; i < 5; i++){QRCode.toDataURL(process.env.QR_CODE_URL+'sku_type'+process.env.QR_CODE_SUFFIX+'item', function(err, url) {
        renderdeet = { item: 'ANYTHING'+i, packingDate:'17-10-2019', type: 'ABC', batch: 'COR01288C', net_qty: '50g', qrCode: url }
    }) 

    app.get('/generateLabel', (req, res) => {
        res.render('index', renderdeet);  
    }
    );
    (async ()=> {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto('http://localhost:5150/generateLabel');
        const dimensions = await page.evaluate(() => {
            return {
              width: document.body.clientWidth,
              height: document.body.clientHeight,
              deviceScaleFactor: 1
            };
          });
          await page.setViewport(dimensions)
        await page.evaluate(() => document.body.style.background = 'transparent');
        await page.screenshot({path: 'outputs/example'+i+'.png', omitBackground: true});
        await browser.close();
      })();
}

    app.listen(port, () => {
    console.log(`listening on port ${ port }`);
    });

预期结果将在输出文件夹中获取100张图片,每张图片具有不同的QR码和标签详细信息。

在实际结果中,由于操纵up功能存在问题,或者存在内存错误(使用此方法)或根本没有获取屏幕截图

1 个答案:

答案 0 :(得分:0)

您正在forloop内创建并执行一个函数,您需要做的是在for循环外创建一个异步函数,然后在for循环内使用await来执行。

第二,您应该在启动循环之前打开浏览器一次,然后在for循环中使用页面实例。

确保循环结束后关闭浏览器。

结构如下:

{libraries}

{Start Browser and save it in a variable}

{loopstart}
    await myfunc(page)
{loopend}

{close browser}

{async myfun(page){}}