You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Puppeteer中等待空闲页面 控制并发标签页数量不超过上限

问题原因

你原来的代码存在两个核心问题:

  • Array.prototype.forEach 不支持异步阻塞,传入的async回调会被同时触发,不会等待前一个回调执行完成再执行下一个,导致所有页面会在短时间内全部新建,并发控制完全失效。
  • 页面关闭逻辑放在迭代内部,可能出现部分任务还没启动浏览器就被关闭的问题,导致任务执行失败。
修正后的实现方案
const puppeteer = require('puppeteer');
// 最大同时打开的业务页面数量,可根据服务器限制调整
const MAX_CONCURRENT_PAGES = 10;

let serialNumbers = ['FVFDT2GCQ6L7', 'DLXFG3X2DFJ1', 'FVFDT2GCQ6L7', 'DLXFG3X2DFJ1', 'FVFDT2GCQ6L7', 'DLXFG3X2DFJ1'];

// 等待空闲页面的工具函数
async function waitForFreePage(browser) {
  while (true) {
    // browser.pages()默认包含1个启动时自带的空白标签页,总页面数=1+业务页面数
    const currentPages = await browser.pages();
    if (currentPages.length - 1 < MAX_CONCURRENT_PAGES) {
      // 存在空闲名额,退出等待
      break;
    }
    // 无空闲页面,等待200ms后再次检查
    await new Promise(resolve => setTimeout(resolve, 200));
  }
}

async function processArray() {
  const browser = await puppeteer.launch({ headless: true });
  // 存储所有任务的promise,用于最后统一等待所有任务完成
  const taskPromises = [];

  // 替换forEach为支持异步阻塞的for...of循环
  for (const item of serialNumbers) {
    // 新建页面前先等待空闲名额
    await waitForFreePage(browser);

    // 启动当前串行号的处理任务
    const task = (async () => {
      const page = await browser.newPage();
      await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36');

      await page.goto(`https://support.apple.com/en_US/specs/${item}`);
      await page.waitForSelector('.article_link');
      await page.click('.article_link');
      await page.waitForSelector('#article');

      const specs = await page.evaluate(() => {
        let article = document.querySelector('h1').innerHTML;
        return `${article}`;
      });

      console.log(specs);
      await page.close();
    })();

    taskPromises.push(task);
  }

  // 等待所有串行号的处理任务全部完成
  await Promise.all(taskPromises);
  // 所有任务完成后再关闭浏览器
  await browser.close();
}

processArray()
关键逻辑说明
  • 替换forEach为for...of循环:for...of支持await阻塞当前迭代,直到等待逻辑执行完成才会进入下一轮迭代,完美匹配需要控制并发的场景的需求。
  • 空闲页等待逻辑:通过循环定期检查当前打开的页面数量,没有空闲名额时就暂停等待,保证同时运行的业务页面数量永远不会超过设定的阈值。
  • 统一等待所有任务完成:通过Promise.all收集所有任务的执行状态,所有任务跑完后再关闭浏览器,避免提前关闭浏览器导致未完成的任务报错。
  • 并发阈值可配置:修改MAX_CONCURRENT_PAGES常量可以根据实际服务器限制灵活调整最大并行数量。

内容的提问来源于stack exchange,提问作者Alexandr Kossykh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:24:04