3

Is there a way to make the javascript await keyword work outside async functions? I would like to be able to freeze the entire call-stack (instead of just the rest of the async function), to be resumed once the particular promise returns a value. Sadly a powerful await like that is currently gimped or not implemented yet. I tried to make nodent.js work, but due to my custom loader and dynamic functions it's unfortunately impractical.

10
  • 1
    "I would like to be able to freeze the entire call-stack..." That means there's a problem with the overall design of the code, because you really don't want to freeze NodeJS's JavaScript thread. Remember, it only has the one. Commented Mar 9, 2017 at 17:43
  • 1
    Freezing the call stack requires freezing the thread, because of JavaScript's run-to-completion semantics. Once a job from the job queue is picked up, it must be run to completion (e.g., the stack unwinds) before that thread is allowed to do anything else. (And no, JavaScript isn't intrinsically single-threaded, but NodeJS runs only a single thread.) Commented Mar 9, 2017 at 17:47
  • 2
    Freezing the call stack is not at all how await actually works. What you're asking for is coroutines. There are some coroutine libs available, but AFAIK nothing that approaches the nice syntax of async/await. Commented Mar 9, 2017 at 17:59
  • 1
    This reminds me a bit of #include "pascal.h" (you're trying to make JS look like something it isn't). Commented Mar 9, 2017 at 18:05
  • 2
    @JohnSmith Why would you want to do that? What is your actual problem? Commented Mar 9, 2017 at 18:28

2 Answers 2

7

Is there a way to make the javascript await keyword work outside async functions?

Sadly, the answer is: No.

See the docs:

The await expression causes async function execution to pause, to wait for the Promise's resolution, and to resume the async function execution when the value is resolved. [emphasis added]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

I would like to be able to freeze the entire call-stack (instead of just the rest of the async function), to be resumed once the particular promise returns a value.

But how could your promise return a value if the entire call-stack was frozen? It would be stuck forever.

More details

To use await you need to be inside async function.

At least you have to do:

async function main() {
  // use await here
}
main();

in your main code.

Or, using an IIFE - thanks to Robert Klep for the suggestion:

void async function main() {
    // use await here
}();

Or, if you like punctuation:

(async () => {
    // use await here
})();

Other options

There are some other options to handle concurrency in Node, like:

none of which will freeze the call stack, however, as it would have the same effect as running kill -STOP with your own process ID and waiting for the stopped process to resume itself.

Sign up to request clarification or add additional context in comments.

13 Comments

It's not sad. :-) Freezing the entire call stack in NodeJS would effectively crash it, as nothing could happen with the one JS thread NodeJS runs frozen like that.
@JohnSmith If your call stack was frozen then how could your promise return a value? It would be frozen like everything else.
@JohnSmith: That would violate the JavaScript spec (details in my comment on the question). (And yes, Firefox did used to do something like that with alert. Hopefully it doesn't anymore, as run-to-completion is an important aspect of the spec now. :-) )
@rsp you could also use an async IIFE: void async function main() { ... }()
@JohnSmith: I think rsp, and robertklep, and I, are all clear on that. We heard you the first time. What we're telling you is: The spec doesn't let you do that. As far as JavaScript is concerned, freezing the callstack requires freezing the thread. That's not true in some other languages, but it is true in JavaScript. So although you don't want to freeze the thread, that would be an inevitable consequence of doing what you have said you want to do.
|
3

Given you are looking for a hack, not a proper promise-based concurrency solution, have a look at node-fibers (there are similar ones, but afaik this is the most popular, with multiple abstractions built around it). It does allow you to halt the current fiber in any synchronous function until something asynchronous happens that runs in a different fiber. Which of course is a horrible idea, but well…

4 Comments

Sure. Or they could switch to running on the JVM and use multiple threads.
@T.J.Crowder You mean, switch from node to rhino? But actually fibers are still better than threads, as they allow you to yield explictly (like coroutines).
I already looked at node-fibers. They seem to be somewhat what I am looking for (context switching and all), though I imagine it'd not be very easy to implement.
@Bergi: Not Rhino, which is ancient. Nashorn. (But I'm not serious. While I'm the one constantly challenging the false claim that JS is single-threaded, I don't advocate leaving Node for the JVM unless you have a broad reason for doing so than not liking async completions.)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.