Puppeteer中waitForNavigation后window.performance.timing未定义问题
嘿,我来帮你搞定这个问题!你遇到的window.performance.timing变为undefined的情况,主要是因为现代浏览器已经逐步废弃了这个旧的API,再加上Puppeteer导航后的上下文时机问题,导致你无法获取到预期的数据。下面给你详细分析和解决方案:
为什么会出现这个问题?
Chrome从版本60开始,就把window.performance.timing标记为废弃状态,取而代之的是标准的PerformanceNavigationTiming接口。在页面完成导航后,旧的timing对象可能会被浏览器清空或者直接无法访问,这就是你看到undefined的原因。另外,如果waitForNavigation的等待时机设置不对,也可能导致你在页面未完全加载时就去读取性能数据,同样会出现异常。
解决方案:改用新的性能API + 正确的导航等待时机
1. 替换为PerformanceNavigationTiming获取性能数据
这个新API是W3C标准的一部分,提供了更丰富、更准确的性能指标。你可以通过performance.getEntriesByType('navigation')[0]获取导航相关的所有性能数据。
2. 确保waitForNavigation使用正确的等待策略
建议使用Promise.all来并行执行点击操作和等待导航,同时指定waitUntil选项为networkidle0(当网络连接数为0且持续500ms时认为页面加载完成),确保页面完全加载后再读取性能数据。
修改后的代码示例
结合你的代码逻辑,调整后的版本如下:
const puppeteer = require('puppeteer'); const USERNAME_SELECTOR = '<value>'; const PASSWORD_SELECTOR = '<value>'; const BUTTON_SELECTOR = '<value>'; const ACCOUNT_SELECTOR = '<value>'; const URL = '<value>'; const CREDS = require('./creds'); async function run() { const browser = await puppeteer.launch({ headless: false }); // 建议直接创建新页面,避免使用pages[0](可能是默认的空白页) const page = await browser.newPage(); await page.goto(URL); // 填写登录信息 await page.type(USERNAME_SELECTOR, CREDS.username); await page.type(PASSWORD_SELECTOR, CREDS.password); // 并行执行点击和等待导航,避免竞态问题 await Promise.all([ page.click(BUTTON_SELECTOR), page.waitForNavigation({ waitUntil: 'networkidle0' }) ]); // 使用新API获取性能数据 const performanceData = await page.evaluate(() => { const navEntry = performance.getEntriesByType('navigation')[0]; if (!navEntry) return null; // 提取你需要的性能指标,示例如下 return { 页面加载总耗时: navEntry.loadEventEnd - navEntry.fetchStart, DOMContentLoaded耗时: navEntry.domContentLoadedEventEnd - navEntry.fetchStart, 服务器响应耗时: navEntry.responseEnd - navEntry.requestStart, 导航类型: navEntry.type // 比如'reload'、'navigate'、'back_forward' }; }); console.log('页面性能数据:', performanceData); // 后续操作(比如获取账户信息) const accountInfo = await page.$eval(ACCOUNT_SELECTOR, el => el.textContent); console.log('账户信息:', accountInfo); await browser.close(); } run().catch(err => console.error('运行出错:', err));
额外注意点
- 如果你的登录操作会打开新标签页,那
waitForNavigation需要监听新页面的导航事件,这时候你需要通过browser.waitForTarget获取新页面的上下文,再在新页面中读取性能数据。 - 如果你必须使用旧的
performance.timing(不推荐),可以尝试在page.goto之后、导航之前读取,但这只能获取初始页面的性能数据,无法获取登录后跳转页面的数据。
内容的提问来源于stack exchange,提问作者Andy Akins
相关产品推荐
相关产品推荐

