javascript - puppeteer evaluate/waitFor 方法中的文档引用

标签 javascript node.js google-chrome-devtools puppeteer

我对 puppeteer evaluate 方法中的 document 引用感到困惑。官方文档有一些代码如下。在waitFor函数中, Node 脚本中有一个文档引用。我知道这些行很可能被执行为:waitForHandler.toString() 然后被传输到浏览器环境以通过 WebSocket 连接运行。无论如何,文档和其他一些变量(例如窗口)在 Node 脚本中出现时确实会引起混淆,不是吗?对此有什么解释吗?

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

最佳答案

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

示例

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

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

解释

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

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

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

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

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

为什么会这样?

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

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

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

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

关于javascript - puppeteer evaluate/waitFor 方法中的文档引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56590926/

相关文章:

javascript - 为什么 setCustomValidity() 在 React 应用程序中不起作用?

javascript - 如何创建一个将任何给定字符串与第二个参数连接起来的函数?

javascript - 如何在 Electron js 中将消息打印到 openDevTools 的控制台?

javascript - Chrome 控制台已经声明变量抛出 let 的 undefined reference 错误

java - 提供 Web 浏览器和 Java 应用程序之间的接口(interface)

javascript - 将所有 TypeScript 文件包含在 .csproj 中后出现 Typescript 错误

javascript - 如何将 uglify-es 与 gulp 一起使用?

javascript - 异步 JS Pre-Ecma2015

node.js - 是否可以将 Http digest auth 与 Uptime 一起使用?

javascript - 'innerHTML'和 'appendChild'的区别