模块范围变量“output”拒绝被异步函数“retrieveTextWrapper”覆盖,我不明白为什么。我的目标是在 StackOverFlow 的主页上输出文本。 retrieveTextWrapper 成功地抓取了这些信息,但我似乎无法将这些内容分配给输出变量。我究竟做错了什么?如何打印从 main() 函数中抓取的信息?
注意:我使用的是 electron 版本 3.0.4,因为在那个版本上绕过 CORS 不那么痛苦。
const {BrowserWindow, app} = require('electron')
output = "this should be overwritten by the retrieveTextWrapper method"
async function main(){
navigate();
win.openDevTools();
await win.webContents.once('dom-ready',retrieveTextWrapper);
console.log(output);
//prints "this should be overwritten by the retrieveTextWrapper method"
}
function navigate() {
win = new BrowserWindow({width:900,height:900});
win.loadURL(`https://stackoverflow.com/`);
}
function retrieveText(){
return `document.querySelector("*").innerText`;
}
async function retrieveTextWrapper(){
output = await win.webContents.executeJavaScript(retrieveText().replace("*", "#content"));
}
app.on('ready',main)
最佳答案
win.webContents.once()
不返回 promise (因为接口(interface)通常不接受两个回调并同时返回 promise )。
因此 await
不会等待异步操作完成。因此,您在重新分配其值之前查看输出。 await
仅在您 await
连接到您尝试等待的异步操作的 promise 时才做一些有用的事情。
要确认此计时问题,请在 await win.webContents.once('dom-ready',retrieveTextWrapper); 之前和之后添加一个独特的
和 console.log()
语句;retrieveTextWrapper
内部,然后您可以看到这些日志消息的顺序。
Yep, everything changes as it should within
retrieveTextWrapper
function. And your explanation makes a lot of sense. However, is it possible to wait for the callback to finish (using some other syntax aside from await)? That way, I can use the updated value for other operations in the main function?
您有几个选择。
您可以“promisify”win.webContents.once()
,这样您就可以对其使用await
。
您可以将回调内联并将其余代码放入该回调内的 main
中(处理异步操作的经典方法)。
这是一个 promise win.webContents.once()
的例子:
function waitForDomReady() {
return new Promise((resolve, reject) => {
// may want to check if document already has dom-ready and resolve immediately
win.webContents.once('dom-ready', resolve);
});
}
然后,您可以像这样使用它:
async function main(){
navigate();
win.openDevTools();
await waitForDomReady();
await retrieveTextWrapper();
console.log(output);
}
这假设 retrieveTextWrapper
中调用 win.webContents.executeJavaScript()
的代码在完成时确实返回了一个 promise 。如果没有,您也必须做出 promise 。
关于javascript - 模块范围变量拒绝被异步函数覆盖。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57350987/