【问题标题】:document reference in puppeteer evaluate/waitFor methodpuppeteer 评估/waitFor 方法中的文档参考
【发布时间】:2019-10-28 15:55:30
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

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

    示例

    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 Parser”仍将解析您的函数)。此外,它还可以让您在代码编辑器中轻松使用语法高亮。

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

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

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

    【讨论】:

    • 很好的解释@thomas-dondorf!我希望这会在 Puppeteer 的文档中被解释为第一件事,但 atm 在这方面找不到任何东西:/
    猜你喜欢
    • 2019-05-13
    • 2023-03-29
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    相关资源
    最近更新 更多