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

使用Playwright实现多用户并行执行UI检查

Playwright多用户并行UI检查实现方案

一、任务拆分逻辑

  • 按用户数量均分数据:5000条数据分给3个用户,前两个用户各处理1666条,第三个用户处理1668条(5000 - 1666*2 = 1668)
  • 用通用chunk函数拆分数组,适配任意用户数量:
function splitArrayIntoChunks(arr, chunkCount) {
  const chunks = [];
  const chunkSize = Math.ceil(arr.length / chunkCount);
  for (let i = 0; i < arr.length; i += chunkSize) {
    chunks.push(arr.slice(i, i + chunkSize));
  }
  return chunks;
}

二、多用户隔离实现

使用Playwright的browser.newContext()创建完全隔离的浏览器上下文,每个上下文对应一个独立用户,拥有专属会话、Cookie和本地存储,完美模拟多用户并发交互。

三、并行执行与任务监控

  • 用Promise.all并行启动所有用户的检查任务
  • 每个任务内部维护进度统计(已处理数、成功数、失败数),实时输出日志
  • 任务结束后汇总所有结果,生成全局报告

四、完整示例代码

const { chromium } = require('playwright');

// 模拟API获取5000条数据(替换为你的API请求逻辑)
async function fetchApiData() {
  return Array.from({ length: 5000 }, (_, idx) => ({ id: idx + 1, content: `Item ${idx + 1}` }));
}

// 单条数据UI检查逻辑(替换成你已实现的脚本)
async function checkSingleItem(page, item) {
  try {
    await page.goto(`https://your-target-url.com/item/${item.id}`);
    await page.waitForSelector(`text=${item.content}`);
    return { itemId: item.id, status: 'success', error: null };
  } catch (err) {
    return { itemId: item.id, status: 'failed', error: err.message };
  }
}

// 单个用户的任务执行函数
async function runUserTask(browser, userDataChunk, userId) {
  const context = await browser.newContext();
  const page = await context.newPage();
  
  // 可添加用户专属登录逻辑(不同用户用不同账号)
  // await page.goto('/login');
  // await page.fill('#username', `user${userId}`);
  // await page.fill('#password', `pass${userId}`);
  // await page.click('text=登录');

  const stats = { processed: 0, success: 0, failed: 0, results: [] };
  
  for (const item of userDataChunk) {
    const result = await checkSingleItem(page, item);
    stats.processed++;
    stats[result.status]++;
    stats.results.push(result);
    
    // 实时输出进度
    console.log(`用户${userId} - 已处理${stats.processed}/${userDataChunk.length} | 成功:${stats.success} | 失败:${stats.failed}`);
  }

  await context.close();
  return { userId, stats };
}

async function main() {
  // 1. 获取API数据
  const apiData = await fetchApiData();
  
  // 2. 拆分成3份任务
  const dataChunks = splitArrayIntoChunks(apiData, 3);
  
  // 3. 启动浏览器(调试时可设headless:false)
  const browser = await chromium.launch({ headless: true });
  
  // 4. 并行执行所有用户任务
  const userTasks = dataChunks.map((chunk, idx) => runUserTask(browser, chunk, idx + 1));
  const allResults = await Promise.all(userTasks);
  
  // 5. 关闭浏览器
  await browser.close();
  
  // 6. 汇总输出最终结果
  console.log('\n=== 最终汇总 ===');
  let totalProcessed = 0, totalSuccess = 0, totalFailed = 0;
  allResults.forEach(({ userId, stats }) => {
    console.log(`用户${userId}: 总处理${stats.processed} | 成功${stats.success} | 失败${stats.failed}`);
    totalProcessed += stats.processed;
    totalSuccess += stats.success;
    totalFailed += stats.failed;
  });
  console.log(`全局统计: 总处理${totalProcessed} | 成功${totalSuccess} | 失败${totalFailed}`);
  
  // 可选:导出失败结果到文件
  // const failedItems = allResults.flatMap(res => res.stats.results.filter(r => r.status === 'failed'));
  // require('fs').writeFileSync('失败项列表.json', JSON.stringify(failedItems, null, 2));
}

// 通用数组拆分函数
function splitArrayIntoChunks(arr, chunkCount) {
  const chunks = [];
  const chunkSize = Math.ceil(arr.length / chunkCount);
  for (let i = 0; i < arr.length; i += chunkSize) {
    chunks.push(arr.slice(i, i + chunkSize));
  }
  return chunks;
}

main().catch(err => console.error('主流程失败:', err));

五、关键注意事项

  • 资源隔离:每个用户使用独立上下文,避免会话、Cookie冲突
  • 错误隔离:单条检查失败不中断整个用户任务,通过内部捕获错误保障流程持续
  • 性能控制:数据量过大时可借助p-limit库限制并发数,避免浏览器资源耗尽
  • 监控扩展:可接入日志库(如winston)或CLI进度条工具,提升监控可视化体验
  • 用户差异化:不同用户的登录、权限逻辑可在runUserTask中单独实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:32:03