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.

- 570
- 2
- 7
- 17
-
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. – T.J. Crowder Mar 09 '17 at 17:43
-
I would like to freeze the call-stack, not the thread. I am aware that javascript is single threaded. – John Smith Mar 09 '17 at 17:45
-
1Freezing 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.) – T.J. Crowder Mar 09 '17 at 17:47
-
2Freezing 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`. – Stephen Cleary Mar 09 '17 at 17:59
-
@StephenCleary I know that await doesn't freeze the call-stack, it is what I would like to do. – John Smith Mar 09 '17 at 18:03
-
1This reminds me a bit of [`#include "pascal.h"`](http://thedailywtf.com/articles/_0x23_include__0x22_pascal_0x2e_h_0x22_) (you're trying to make JS look like something it isn't). – robertklep Mar 09 '17 at 18:05
-
2@JohnSmith Why would you want to do that? What is your [actual problem](http://meta.stackexchange.com/q/66377)? – Bergi Mar 09 '17 at 18:28
-
@Bergi I am working on a personal project that is in itself scriptable. It works with wrappers for types such as one for functions, which I want to be able to queue asynchronous tasks in an opaque way. Blocked calls (for example by user-code) should be turned into tasks that get processed in a fifo queue and return to the calling code without the need for callbacks being setup. – John Smith Mar 09 '17 at 18:42
-
@JohnSmith Then use promises. There's nothing that says that the user code could not be an `async function`. – Bergi Mar 09 '17 at 18:47
-
Possible duplicate of [JavaScript await by default instead of manually](http://stackoverflow.com/questions/42147316/javascript-await-by-default-instead-of-manually) – jib Mar 10 '17 at 04:54
2 Answers
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:
- https://www.npmjs.com/package/co
- https://www.npmjs.com/package/bluebird-co
- https://www.npmjs.com/package/async-co
- http://bluebirdjs.com/docs/api/promise.coroutine.html
- http://taskjs.org/
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.

- 107,747
- 29
- 201
- 177
-
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. – T.J. Crowder Mar 09 '17 at 17:44
-
-
@T.J.Crowder Yeah, that's what I was just adding in the update. :) Once again, thanks for the comment. – rsp Mar 09 '17 at 17:47
-
1@JohnSmith If your call stack was frozen then how could your promise return a value? It would be frozen like everything else. – rsp Mar 09 '17 at 17:49
-
@rsp I want to freeze the call-stack, not the thread. I want the thread to resume the call-stack once the promise value is available, meanwhile it could do other things. – John Smith Mar 09 '17 at 17:49
-
1@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. :-) ) – T.J. Crowder Mar 09 '17 at 17:53
-
1@rsp you could also use an async IIFE: `void async function main() { ... }()` – robertklep Mar 09 '17 at 17:57
-
again, I am not trying to pause the main thread, just the switch the context until the promise returns and then switch back to it. I have read what @rsp wrote about run-to-completion and I can see where it comes from, it's just that I want to do it anyways. – John Smith Mar 09 '17 at 18:07
-
@JohnSmith: Again: You can't, in a JavaScript engine that isn't broken (and V8 isn't). The spec is quite clear about not allowing what you're describing. It's not that what you're describing is weird or alien or wrong (it *is* very complicated to program against, leading to all kinds of nasty side-effects and bugs, but it's not wrong or unreasonable as a concept), it's just not allowed in JavaScript. Instead, we have asynchronous completions. – T.J. Crowder Mar 09 '17 at 18:14
-
@JohnSmith It's not that you couldn't freeze the execution of your code - you could for example run `process.kill(process.pid, 'SIGSTOP');` - the problem is that you couldn't resume without some other process waking you up. – rsp Mar 09 '17 at 18:17
-
again, I am not trying to pause or stop the main thread, just the switch the context until the promise returns and then switch back to it. – John Smith Mar 09 '17 at 18:20
-
1@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. – T.J. Crowder Mar 09 '17 at 18:36
-
Yes, I accept that it's against the spec. I would have no problem working with a hack, or some kind of unconventional engine. Fibers have also been suggested, which basically allow for thread-contexts being switched and resumed. – John Smith Mar 09 '17 at 19:00
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…
-
Sure. Or they could switch to running on the JVM and use multiple threads. – T.J. Crowder Mar 09 '17 at 18:37
-
@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). – Bergi Mar 09 '17 at 18:45
-
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. – John Smith Mar 09 '17 at 18:48
-
@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.) – T.J. Crowder Mar 09 '17 at 22:06