Playwright 的 download 事件对象本身不包含下载耗时信息,需通过手动记录起止时间戳(如 Date.now())来计算完整下载时长。
playwright 的 `download` 事件对象本身不包含下载耗时信息,需通过手动记录起止时间戳(如 `date.now()`)来计算完整下载时长。
在自动化测试或性能监控场景中,精确测量文件下载耗时至关重要。虽然 Playwright 提供了 request.timing() 方法用于获取网络请求各阶段的详细时间(如 DNS 查询、TCP 连接、TLS 握手等),但该方法仅适用于 Request 对象,而 Download 对象不暴露 timing 属性,也无法直接关联底层请求——因为下载可能由 触发、重定向链复杂,或经由浏览器原生下载流程处理,Playwright 并未将下载过程映射为可追踪的单一网络请求。
因此,最可靠且通用的方式是采用「端到端时间戳法」:在触发下载操作前记录开始时间,在成功捕获 download 事件后记录结束时间,二者之差即为用户感知的完整下载耗时(含页面交互延迟、服务响应、网络传输及浏览器写入磁盘时间)。
以下为推荐实现方式(使用 Promise.all 避免竞态,确保计时精度):
const startTime = Date.now();
// 同时启动下载监听与点击操作,避免因异步顺序引入额外延迟
const [download] = await Promise.all([
page.waitForEvent("download", { timeout: 35000 }),
page.getByRole("button", { name: "Download" }).click({ timeout: 35000 })
]);
const endTime = Date.now();
const durationMs = endTime - startTime;
console.log(`✅ Download completed in ${durationMs} ms`);
// 可选:进一步验证下载结果
await download.path(); // 等待文件写入完成(返回 Promise<string>)</string>
⚠️ 注意事项:
- 勿单独 await click() 再 await waitForEvent:这会引入不必要的等待间隙,导致计时不准确;务必使用 Promise.all 并发执行;
- 超时设置需一致:waitForEvent 和 click() 的 timeout 应保持相同(如示例中的 35000 ms),防止任一环节提前失败中断流程;
- download.path() 是关键确认点:download 对象被创建仅表示浏览器已发起下载,不代表文件已保存完毕;调用 await download.path() 可确保文件写入完成,适合需要后续校验文件内容的场景;
- 若需更高精度(亚毫秒级),可改用 performance.now(),但对绝大多数下载场景,Date.now() 已足够且兼容性更佳。
该方案简洁、稳定、不依赖内部 API,是 Playwright 官方推荐的下载耗时测量实践。











