javascript - 模块范围变量拒绝被异步函数覆盖。为什么?

标签 javascript node.js asynchronous electron

模块范围变量“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/

相关文章:

javascript - cookie 和重定向

node.js - Mongoose 连接方法在简单 Node 服务器上失败。 express 、 Mongoose 、路径

javascript - 合理数量的同时异步 ajax 请求

javascript - 在 React 类之间传递数据不起作用

javascript - Jquery自动幻灯片排序问题

javascript - 如何在 JavaScript 中使用 dd/mm/yyyy 格式计算年龄?

node.js - 为什么我会得到之前的选项卡 url?

Node.js 已安装但无法使用

java - Spring - @Async 在手动创建组件时不起作用

javascript - 处理许多异步请求