如何向箭头函数传参?Puppeteer $$eval回调selector未定义报错
问题根因
page.$$eval的执行逻辑是:将传入的回调函数序列化为字符串,直接注入到浏览器的页面上下文中运行,整个执行过程和Node.js运行环境完全隔离,回调内部无法通过闭包访问Node.js侧作用域的任何变量。
你代码中引用的selector、contractsPo都是Node.js侧定义的变量,从来没有被传入浏览器的执行环境,所以执行到if判断语句时,就会抛出ReferenceError: selector is not defined的错误。
修复方案
page.$$eval支持可变额外传参:从函数的第三个入参开始,所有传入的值都会被序列化后透传到浏览器的回调执行上下文,作为回调的形参按顺序接收。只需要把回调内部要用到的外部值,全部通过这个渠道传入即可解决问题。
修正后的代码实现
static async valuesToArray(selector: string): Promise<void> { // 提前取出需要在页面回调中使用的具体常量值 const dateColSelector = contractsPo.contractDateCol; const data: (string | Date)[] = await page.$$eval( selector, // 回调的形参顺序,和透传的参数顺序一一对应 (cells, currentSelector, targetDateSelector) => { return cells.map(cell => { if (currentSelector === targetDateSelector) { return new Date( cell.textContent!.replace(/(\d{2}).(\d{2}).(\d{4})/, '$2/$1/$3'), ); } else { return cell.textContent!; } }); }, // 以下为需要透传到浏览器执行环境的参数 selector, dateColSelector ); }
注意事项
- 回调运行在浏览器的独立执行环境,不能依赖Node.js的闭包机制读取外部变量,所有回调内部要用到的外部值,必须通过$$eval的额外参数显式传递。
- 透传的参数必须是支持结构化克隆的纯数据,比如字符串、数字、普通对象、数组,不能传Node.js侧的函数、类实例、带自定义方法的对象,否则会在序列化阶段直接报错。
- 如果用到的选择器是固定常量,也可以直接把值硬编码在回调内部,省去不必要的参数透传步骤。
内容的提问来源于stack exchange,提问作者Vladimir Krygin
相关产品推荐
相关产品推荐

