如何等待Puppeteer打印到打印机的任务执行完成,无需设置固定超时?
问题原因
你遇到的核心问题是window.print()属于浏览器异步非阻塞API,调用后不会等待打印任务提交到系统打印队列就会立刻返回执行后续代码,直接调用browser.close()或者跳转页面会直接中断未完成的打印流程,固定时长的waitForTimeout完全依赖环境状态,不可靠。
最优解决方案:监听afterprint原生事件
浏览器原生提供了afterprint事件,会在打印任务成功提交到系统打印队列后触发(不需要等待打印机物理打印完成,只要任务进入系统队列关闭浏览器就不会影响打印),完全不需要硬编码等待时长,适配所有场景。
修改后的完整代码如下:
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: false, args: [ "--kiosk-printing" ] }); const page = await browser.newPage(); await page.goto(`file:///C:/Users/srich/Downloads/packing-list.pdf`); // 执行打印并等待提交完成 await page.evaluate(() => { return new Promise(resolve => { // 监听打印完成事件后resolve,once保证只触发一次 window.addEventListener('afterprint', resolve, { once: true }); window.print(); }); }); // 打印任务已提交,可直接关闭浏览器 await browser.close(); })();
备选方案:监听CDP打印任务完成事件
如果有特殊场景无法监听afterprint事件,可以调用Chrome DevTools Protocol(CDP)的Printing域接口,直接监听打印任务完成状态:
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: false, args: [ "--kiosk-printing" ] }); const page = await browser.newPage(); await page.goto(`file:///C:/Users/srich/Downloads/packing-list.pdf`); // 初始化CDP客户端,启用Printing域 const cdpSession = await page.createCDPSession(); await cdpSession.send('Printing.enable'); // 等待打印任务完成的Promise const printJobDone = new Promise(resolve => { cdpSession.once('Printing.jobCompleted', resolve); }); // 执行打印 await page.evaluate(() => window.print()); // 等待打印任务完成 await printJobDone; await browser.close(); })();
为什么之前跳转页面的方案无效
跳转页面会立刻中断当前页面的所有正在执行的异步任务,包括未提交完成的打印流程,所以打印任务还没发出去就被中止了。
内容的提问来源于stack exchange,提问作者RockBoro
相关产品推荐
相关产品推荐

