为了账号安全,请及时绑定邮箱和手机立即绑定

puppeteer 评估/waitFor 方法中的文档参考

puppeteer 评估/waitFor 方法中的文档参考

翻阅古今 2021-06-29 09:51:50
我document对 puppeteerevaluate方法中的参考感到困惑。官方文档有一些代码如下。在waitFor函数中,节点脚本中有文档引用。我确实理解这些行很可能被执行为:waitForHandler.toString()然后被传输到浏览器环境以通过 WebSocket 连接运行。无论如何,文档和其他一些变量(例如window)在节点脚本中出现时确实会引起混淆,不是吗?对此有任何解释吗?await page.waitFor(() => !!document.querySelector('.foo'));
查看完整描述

1 回答

?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

是的,你说得很对,这可能会引起混淆。


例子


const document = /* ... */;

await page.waitFor(() => !!document.querySelector('.foo'));

看起来代码正在document从上面访问变量,但这实际上并不是这里发生的事情,即使您的 IDE/语法高亮可能会告诉您它是相同的变量。


解释


Node.js 环境和浏览器环境是两个独立的 (JavaScript) 环境,它们通过 WebSocket 进行通信。因此,当您在 Node.js 环境中的页面上执行函数时,puppeteer 需要将该函数作为字符串发送到浏览器。对于这个puppeteer 将调用toString()给定函数上的函数,该函数只返回您写下的高级代码。该字符串将被发送到浏览器并在其环境中执行。


这也是您可以将字符串而不是函数传递给 puppeteer 的原因。如果您提交的是字符串而不是函数,则代码将在浏览器环境中执行。


举个例子,考虑这两行,它们做同样的事情(打印123到控制台):


console.log(await page.evaluate(() => 123));

console.log(await page.evaluate('(() => 123)()'));

在第一行中,该函数作为函数传递(并且 puppeteer 会将其转换为字符串并为您调用该函数)。在第二行中,传递了相同的函数,但这次我们必须自己调用它(函数周围的额外括号仅出于语法原因才需要)。


为什么它会这样工作?


为方便起见,Puppeteer 允许将函数作为函数(而不仅仅是作为字符串)传递。允许这样做,可以很容易地发现任何小错误,例如缺少括号,因为它们已经被您的 Node.js 环境拾取(您的“Node.js JavaScript Parser”仍将解析您的函数)。此外,它还可以轻松地在您的代码编辑器中使用语法高亮。


但是,是的,很容易忘记这个抽象层意味着您使用的任何参数都需要作为单独的参数传递,如下所示:


const value1 = 123;

await page.evaluate((value1) => { /... */ }, value1);

总而言之,如果您发现它令人困惑,您始终可以将代码放入一个单独的文件中,读取该文件并将其内容作为字符串在调用 puppeteer 函数时传递。这允许更好地分离您的代码。值得付出努力吗?你必须自己决定...


查看完整回答
反对 回复 2021-07-01
  • 1 回答
  • 0 关注
  • 441 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信