javascript - 模块范围变量拒绝被异步函数覆盖。为什么?
问题描述
模块范围变量“输出”拒绝被异步函数“retrieveTextWrapper”覆盖,我不知道为什么。我的目标是在 StackOverFlow 的主页上输出文本。retrieveTextWrapper 成功地抓取了这些信息,但我似乎无法将此内容分配给输出变量。我究竟做错了什么?如何从 main() 函数打印抓取的信息?
注意:我使用的是电子版本 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()
不返回承诺(因为接口通常不会同时接受回调和返回承诺)。
因此await
不等待异步操作完成。因此,您在重新分配其值之前查看输出。仅当您连接到您尝试等待的异步操作的承诺await
时才会做一些有用的事情。await
要确认这个时序问题,在 ofconsole.log()
之前和之后添加一个唯一的语句,然后您可以看到这些日志消息的顺序。await win.webContents.once('dom-ready',retrieveTextWrapper);
retrieveTextWrapper
是的,一切都在
retrieveTextWrapper
功能范围内发生变化。你的解释很有道理。但是,是否可以等待回调完成(使用 await 之外的其他语法)?这样,我可以将更新后的值用于主函数中的其他操作吗?
你有几个选择。
你可以“承诺” win.webContents.once()
,这样你就可以使用await
它了。
您可以将回调内联并将其余代码main
放入该回调中(处理异步操作的经典方式)。
这是一个承诺的例子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()
完成时确实返回了一个承诺。如果没有,你也必须承诺。
推荐阅读
- c# - 在 WebApi 中实现 IAuthenticationFilter
- antlr4 - 如何解析由多字符分隔符分隔的文本列表
- node.js - 从角度发送数据到节点api
- sapui5 - 是否可以在 SAP Fiori 列表中交替行颜色?
- kubernetes - Kubernetes StatefulSet - 不会在 pod 重启时恢复数据
- java - 如何在 PPA 中安装旧的 java 版本?
- java - @MockBean 不适用于带有 JUnit 5 和 Sping Boot 2 的 @WebMvcTest?
- xamarin.forms - Zxing Mobile 崩溃我的应用程序 Java.Lang.RuntimeException
- javascript - initialvalues is not shown in react-select when using with redux form
- python - 如何在python igraph的图中保留顶点标签