Module-scope variable refuses to be overwritten by an async function. Why?

Guy4444

The module-scope variable "output" refuses to be overwritten by the async function "retrieveTextWrapper", and I cannot figure out why. My objective is to output the text on StackOverFlow's homepage. retrieveTextWrapper successfully scrapes this information, but I can't seem to assign this content to the output variable. What am I doing wrong? How can I print the scraped information from the main() function?

Note: I am using electron version 3.0.4 because bypassing CORS is less of a pain on that version.

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)
jfriend00

win.webContents.once() does not return a promise (since interfaces generally don't accept both callbacks and return a promise at the same time).

Therefore await doesn't wait for the asynchronous operation to complete. Therefore, you're looking at output before its value has been reassigned. await only does something useful when you await a promise that is connected to the asynchronous operation you're trying to wait for.

To confirm this timing issue, add a unique console.log() statement before and after the await win.webContents.once('dom-ready',retrieveTextWrapper); and inside of retrieveTextWrapper and then you can see the sequencing of these log messages.

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?

You have a couple options.

You could "promisify" win.webContents.once() so you could then use await with it.

You could put the callback inline and put the rest of your code in main inside that callback (a classic way of dealing with asynchronous operations).

Here's an example of promisifying 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);
    });
}

And, you could then use it like this:

async function main(){
   navigate();
   win.openDevTools();
   await waitForDomReady();
   await retrieveTextWrapper();
   console.log(output);
}

This assumes that the code in retrieveTextWrapper that calls win.webContents.executeJavaScript() does actually return a promise when it's done. If not, you have to promisify that too.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why can't a variable be overwritten under a function?

$scope variable refuses to change value within wavesurfer's function handler

Variable is overwritten in asynchronous function with async.forEach loop

Why is the function argument not overwritten on creating variable of same name inside the function?

Why isn't my local variable being overwritten in this function?

Initialization of a static variable in the scope of a function or a module

How to access the async/await scope variable out of the async function?

Variable value overwritten in getJSON function

Why is a universally quantified variable not in scope in this Haskell function?

Variable scope in async functions

How do I assign a variable defined in a synchronous scope in an async function?

monkeypatch function in module whose namespace was overwritten

variable scope within a module

Local function variable change not effecting variable in global scope. Why not?

Why is variable overwritten in Ansible inventory configuration

Nested async functions variable scope

Why my struct created in function gets overwritten?

Function with for loop: Why is 1 not overwritten by 5?

In AngularJS, why isn't a $scope variable accessible from a simple function?

Angular $scope property gets overwritten when passed into function as an argument

Why is "Variable not in scope"

Why is this variable out of scope?

How can I refer to a module variable in a function without referring to its module in Elixir 1.0.3? In its parent scope?

Scope of a variable and function name

Variable scope in function closure?

Scope of an outer function variable?

Variable scope of callback function

Defining variable scope in function

Nested function scope variable