-2

EDIT: Someone has marked this question as closed because there are already answers on other similar questions. However, none of the other questions provide a solution to my question.

I am struggling with this seemingly most basic task. I have an async function asyncFunc() that reads a file, but for simplicity let's say this function returns "Hello world". I run the following code in my app.js top-level file.

console.log('Getting mydata...')
mydata = asyncFunc()
console.log('My data is', mydata)
process.exit()

When I run this the output is

Getting mydata...
mydata is Promise {[[PromiseState]]: 'pending'

The output that I want is:

Getting mydata...
mydata is Hello World

I have tried following the suggestion of @splichte in this github post about the issue and using the code below. But I get the same incorrect output as before. https://github.com/Keyang/node-csvtojson/issues/278

async function run() {
  const data = await asyncFunc();
  return data
}
 
console.log('Getting mydata...')
mydata = run()
console.log('My data is', mydata)
//continue with rest of my program
//many sections of which will use mydata
process.exit()

I have tried the suggestion of using myData = await run() but this gives the error

await is only valid in async functions and the top level bodies of modules

Can someone please post some example code to get the desired output below?

Getting mydata...
mydata is Hello World
Eyles IT
  • 1
  • 1
  • Put your code in an async function and do `myData = await run()`. The reason `run` returns a promise is that it's an `async` function. – Nicholas Tower Aug 22 '23 at 20:31
  • @Nicholas Tower, thanks for the comment, but that does not work. When I use `myData = await run()` I get the error **await is only valid in async functions and the top level bodies of modules** – Eyles IT Aug 23 '23 at 09:25
  • Put all your code *inside* the `run` function, and have it use the `const data` not the global `mydata`. Please read all the answers to the duplicate questions in detail. – Bergi Aug 23 '23 at 09:36
  • https://stackoverflow.com/questions/67688570/error-in-global-call-to-async-function-await-is-only-valid-in-async-functions is the first hit on Google when I copy/paste the error message. – Quentin Aug 23 '23 at 09:39
  • Thanks for the comment, Bergi, but that does not achieve what I want to do. In the top-level app.js I want to call the function `asyncFunc()` to retrieve the contents of the file, then assign that data to a global variable, then do some processing on that data but only when the data is there. If you have a working example please post the code. – Eyles IT Aug 23 '23 at 09:59
  • You can (a) Use a module (b) Use an async IIFE (c) Use `then` instead of `await`. You **cannot** return an async value in the top level outside a module; the error message makes that pretty clear. – Quentin Aug 23 '23 at 10:09
  • Quentin, I assume you mean your answer in the link you posted which describes making a Javascript file a module? My code is in the server-side app.js. The answer you gave applies to scripts referenced in the client-side for the browser. – Eyles IT Aug 23 '23 at 10:14
  • @Quentin thanks for the suggestions. I tried "(b) Use an async IIFE". It did not work. The code I tried is: `var mydata; (async () => { mydata = await asyncFunc() })(); console.log('mydata is', mydata) process.exit()` The output was "mydata is undefined", which is NOT what I want. – Eyles IT Aug 23 '23 at 10:30
  • @EylesIT – I said "You cannot return an async value in the top level outside a module". Using an IIFE doesn't change that. You need to use the variable **inside** the IIFE. – Quentin Aug 23 '23 at 10:33
  • @EylesIT — [Node.js supports modules](https://nodejs.org/api/esm.html#enabling). – Quentin Aug 23 '23 at 10:34
  • @Bergi, your suggestion to put all the code inside the function and to use the local variable does not solve the problem. The problem I want to solve is to call the function, get the results into a global variable, and then do something with the data in that global variable. – Eyles IT Aug 23 '23 at 10:37
  • 1
    For the third time (not counting the duplicate questions or other people's comments): **You can't do that!** – Quentin Aug 23 '23 at 10:39
  • @EylesIT "*get the results into a global variable, and then do something with the data in that global variable*" - **That is not possible!** (Unless you use a module with top-level `await`, which apparently you don't). – Bergi Aug 23 '23 at 10:56
  • @Quentin, many people posted commented giving suggestions to do what you now say cannot be done. That makes it confusing when what I am trying to do is impossible in Javascript and node.js. The question is: what is a workaround? Once I call the function asyncFunc() to get the file data, how do I ensure my app can continue to execute but does not attempt to use the data when it is not there? – Eyles IT Aug 23 '23 at 10:57
  • 1
    @EylesIT Trying to assign a top-level variable from an async function is not going to work, not matter what you try. Doesn't matter whether it's using `.then()`, `run()`, an IIEFE or something else. Just suck it up and put the code *inside* the function (after the `await`) so that your application works. That is the "workaround" you're asking for. – Bergi Aug 23 '23 at 10:59
  • 1
    "*many people posted commented giving suggestions to do what you now say cannot be done.*" then many people are wrong. Or you've not correctly read what they said. It is ***not possible*** to convert a promise to a synchronous value synchronously. If you think about the very nature of what async code is, it's self-evident. It doesn't happen now. You cannot order a pizza and eat it before it's delivered. – VLAZ Aug 23 '23 at 11:03
  • 2
    @EylesIT Not sure which "many people" you are referring to, but here's three of us (Quentin, VLAZ and myself) all saying the same. – Bergi Aug 23 '23 at 11:09
  • We're all suggesting things you can do **instead** of having a global. (e.g. having it as a function scope variable in an IIFE or a module scope variable in a module). – Quentin Aug 23 '23 at 11:13
  • @VLAZ "it's self-evident". Except that you CAN do it in modules. It appears to be an arbitrary restriction put on top-level modules for some reason. – Eyles IT Aug 23 '23 at 11:21
  • 1
    Using `await` at the top level in a module, makes the module asynchronous. Which follows basically the same semantics as everything else - it's async all the way down, if you use that async module anywhere else. It's not arbitrary. Before top-level await you could basically do the same but you'd export promises. Which has the same effect in the end, it's just more annoying to work with. Top level await is a convenience, not some radically new way to process the code in modules. It's not magical in its nature. Just tucks away the promises that were also there. And ensures more compatibility. – VLAZ Aug 23 '23 at 11:24
  • Thanks for all your replies. There is obviously a steep learning curve moving to syncronous/asyncronous/promise programming. Some very non-intuitive situations. – Eyles IT Aug 23 '23 at 11:36

0 Answers0