后台页面中声明的全局函数不会通过 evaluateHandle 调用
Global function declared in background page does not get called via evaluateHandle
我在后台页面中有一个全局函数,如下所示:
window.myfn = function(){
return new Promise((resolve, reject) => { stuff; });
};
我正在使用 Jest 和 Puppeteer。在我的 test.js
文件中考虑这一点:
async function getBackgroundPage() {
const targets = await browser.targets(),
backgroundPageTarget = targets.find(
target => target.type() === "background_page",
),
backgroundPage = await backgroundPageTarget.page();
return backgroundPage;
}
async function sendUpdate() {
const bgPage = await getBackgroundPage(),
argString = `() => window.myfn()`;
await bgPage.evaluateHandle(argString);
await sleep(30000);
}
getBackgroundPage
是从 docs 字面上复制的,所以我希望它是正确的。但是,sendUpdate()
没有按预期工作。理想情况下,应该调用 window.myfn
但实际上它从未被调用过。我知道这是因为:
- 我在里面放了几个
console.log
,所以如果它被调用,应该会有一些日志输出。
- 30 秒的睡眠让我有足够的时间转到
chrome://extensions
,并通过 Inspect Views 打开后台页面控制台,但我在那里找不到任何日志输出。
后台页面和Jest控制台都没有报错。那问题是什么?为什么那个全局函数没有被调用?
给函数和给 evaluateHandle
(和 evaluate
)函数提供字符串之间存在细微差别。
如果传递一个函数,该函数将在页面内部被调用。如果传递一个字符串,该字符串将在页面上下文中执行。这意味着,这两行做不同的事情:
await bgPage.evaluate(() => console.log("test"););
await bgPage.evaluate('() => console.log("test");');
第一行将执行页面内的函数(和运行 console.log
)。但是,第二行只会声明函数而不会调用它。因此,如果我们传递一个字符串,我们必须做这些事情之一:
await bgPage.evaluate('console.log("test")'); // directly run console.log
await bgPage.evaluate('(() => console.log("test"))()'); // execute the function
正在修复您的代码
回到您的代码,这意味着您要么直接调用 window.myfn()
,要么将参数作为函数传递:
await bgPage.evaluateHandle('window.myfn()'); // directly call the function
await bgPage.evaluateHandle(() => window.myfn()); // or pass as a function and not as string
我在后台页面中有一个全局函数,如下所示:
window.myfn = function(){
return new Promise((resolve, reject) => { stuff; });
};
我正在使用 Jest 和 Puppeteer。在我的 test.js
文件中考虑这一点:
async function getBackgroundPage() {
const targets = await browser.targets(),
backgroundPageTarget = targets.find(
target => target.type() === "background_page",
),
backgroundPage = await backgroundPageTarget.page();
return backgroundPage;
}
async function sendUpdate() {
const bgPage = await getBackgroundPage(),
argString = `() => window.myfn()`;
await bgPage.evaluateHandle(argString);
await sleep(30000);
}
getBackgroundPage
是从 docs 字面上复制的,所以我希望它是正确的。但是,sendUpdate()
没有按预期工作。理想情况下,应该调用 window.myfn
但实际上它从未被调用过。我知道这是因为:
- 我在里面放了几个
console.log
,所以如果它被调用,应该会有一些日志输出。 - 30 秒的睡眠让我有足够的时间转到
chrome://extensions
,并通过 Inspect Views 打开后台页面控制台,但我在那里找不到任何日志输出。
后台页面和Jest控制台都没有报错。那问题是什么?为什么那个全局函数没有被调用?
给函数和给 evaluateHandle
(和 evaluate
)函数提供字符串之间存在细微差别。
如果传递一个函数,该函数将在页面内部被调用。如果传递一个字符串,该字符串将在页面上下文中执行。这意味着,这两行做不同的事情:
await bgPage.evaluate(() => console.log("test"););
await bgPage.evaluate('() => console.log("test");');
第一行将执行页面内的函数(和运行 console.log
)。但是,第二行只会声明函数而不会调用它。因此,如果我们传递一个字符串,我们必须做这些事情之一:
await bgPage.evaluate('console.log("test")'); // directly run console.log
await bgPage.evaluate('(() => console.log("test"))()'); // execute the function
正在修复您的代码
回到您的代码,这意味着您要么直接调用 window.myfn()
,要么将参数作为函数传递:
await bgPage.evaluateHandle('window.myfn()'); // directly call the function
await bgPage.evaluateHandle(() => window.myfn()); // or pass as a function and not as string