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

时间:2019-06-14 03:13:37

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

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

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

1 个答案:

答案 0 :(得分: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解析器”仍会解析您的函数)。另外,它还使在代码编辑器中使用语法突出显示变得容易。

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

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

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