使用Puppeteer page.evaluate获取CLS值,无法在浏览器上下文外使用
问题描述
我正在使用page.evaluate在浏览器中记录每个CLS条目,并尝试将其保存到可在浏览器上下文外使用的变量中,代码如下:
page.exposeFunction('getCLSEntries', list => { //console.log("list:", list); let clsList = JSON.parse(list); return clsList; }); console.log("CLS List:", clsList); let cls = new Map(); while (scrollCount < maxScrolls) { //console.log("Function exposed") cls[scrollCount] = await page.evaluate(() => { console.log("reportCLSInstances called"); let clsEntries = []; let clsInstances = []; const internalCLSInstances = (list) => { clsEntries = list.getEntries(); const entries = JSON.stringify(clsEntries); window.getCLSEntries(entries).then((value) => { clsInstances.push(value); console.log("value: ", value); }); console.log("CLS Instances 1:", clsInstances); }; const observer = new PerformanceObserver(internalCLSInstances); observer.observe({type: 'layout-shift', buffered: true}); console.log("CLS Instances 2:", clsInstances); return clsInstances; }); console.log("CLS: ", cls);
但每次page.evaluate都返回[],即便返回前的日志显示数组已填充。当我将返回值改为["hello"]时,却能正常填充Map。请问我哪里操作有误?
问题原因与解决方案
核心问题:异步逻辑未同步等待
PerformanceObserver的回调是异步触发的,你在page.evaluate中直接同步返回clsInstances时,回调还没执行,数组自然为空。另外,window.getCLSEntries是异步函数(exposeFunction暴露的函数本质返回Promise),你在回调里调用它却未等待,即便回调触发,push操作也在then中异步执行,返回时数组依然是空的。修复方案
- 将浏览器上下文内的逻辑包装为Promise,等待CLS条目收集完成后再返回结果:
cls.set(scrollCount, await page.evaluate(async () => { return new Promise(resolve => { const clsInstances = []; const handleCLSEntries = (list) => { const entries = list.getEntries(); clsInstances.push(...entries); // 若仅需获取缓冲的历史条目,收集后直接resolve resolve(clsInstances); // 若需持续监听实时偏移,可设置结束条件(如等待滚动停止、延迟一段时间)后再resolve }; const observer = new PerformanceObserver(handleCLSEntries); observer.observe({type: 'layout-shift', buffered: true}); }); })); - 移除冗余的
exposeFunction:page.evaluate支持直接返回可JSON序列化的对象,无需通过暴露函数来回传数据,直接在浏览器上下文收集条目后返回即可,避免异步嵌套问题。 - 修正
Map的使用方式:你当前用cls[scrollCount]是给对象添加属性,并非Map的正确操作,应使用cls.set(scrollCount, 结果)来添加键值对。
- 将浏览器上下文内的逻辑包装为Promise,等待CLS条目收集完成后再返回结果:
内容的提问来源于stack exchange,提问作者as07
相关产品推荐
相关产品推荐

