3

If I start a node REPL and call a function that returns a promise, the function (obviously) returns immediately and some information about the promise is displayed in the console:

$> node
> var foo = () => new Promise((resolve, reject) => setTimeout(resolve('yay'), 1000));
undefined
> foo().then(console.log)
Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }

Is there any way I can get node to wait, synchronously, for the promise to resolve (or reject) so that I can get the result printed to the console?


I've seen questions like this one but the solutions there all suggest tacking on a .then() call to do what I want with the result (e.g. log it). However, that doesn't seem to work - note that I already have that in my example, but I never get any log output, so I need some other mechanism to keep the process spinning for long enough that I get to see the output (the string 'yay' in the example).

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
  • which node version? node v7.6.0+ supports `await` – hisener Sep 05 '17 at 14:01
  • you could use [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) if your node-version supports it. But that's not really sync either, it's just sugar. Or you continue, and use the returned promises `then()` method to deal with the value it resolves to. – Thomas Sep 05 '17 at 14:01
  • Hack and force a single-threaded engine to block synchronously = very, _very_ bad idea. Embrace asynchronism and learn how to deal with it = way to go. – Jeremy Thille Sep 05 '17 at 14:04
  • 2
    @JeremyThille This particular question however is specifically about inspecting and interacting with values in REPL. Whether it's or not it's idiomatic Node/JS is not really relevant in this case. – Emil Lundberg Sep 05 '17 at 14:08
  • @hisener: node v8.1.2 in this case. – Tomas Aschan Sep 05 '17 at 14:08
  • @Thomas: No, because in order to use `await` I have to be in an `async` context, and I can't figure out how to create an `async` context that doesn't just print the promise and exit. – Tomas Aschan Sep 05 '17 at 14:09
  • Nevertheless, I can't help warning about this terrible idea. Then OP can do what they want :) – Jeremy Thille Sep 05 '17 at 14:10
  • @JeremyThille: What Emil said. I'm not doing this as part of my application - I'm doing it as part of my development and debugging workflow. I need some way to inspect what an asynchronous function does, from the Node REPL, so a hack is totally fine, because it's never going into production code. – Tomas Aschan Sep 05 '17 at 14:11
  • Possible duplicate of [How to wait for a JavaScript Promise to resolve before resuming function?](https://stackoverflow.com/questions/28921127/how-to-wait-for-a-javascript-promise-to-resolve-before-resuming-function) – Emil Lundberg Sep 05 '17 at 14:11
  • @EmilLundberg: Nope, none of those answers solve my problem. – Tomas Aschan Sep 05 '17 at 14:18
  • The accepted answer does answer your question as "no, it's impossible", though. :) – Emil Lundberg Sep 05 '17 at 14:22
  • Have a look at https://stackoverflow.com/questions/44169542/how-to-resolve-promises-when-using-app-with-repl. Or of course, you'd [just use `await foo()`](https://github.com/nodejs/node/issues/13209) :-) – Bergi Sep 05 '17 at 17:02

3 Answers3

2

As of version 8.4.0 the Node REPL actually shows the value of a resolved Promise when printing it:

$ node --version
v8.4.0
$ node
> var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 3000));
undefined
> var p = foo()
undefined
> p
Promise {
  <pending>,
    domain: // Omitted for brevity
}
> // Wait 3 seconds...
> p
Promise {
  'yay',
  domain: // Omitted for brevity
}

As you can see, the <pending> is replaced with 'yay' when the Promise resolves.

Emil Lundberg
  • 7,268
  • 6
  • 37
  • 53
  • 1
    You code is not totally correct, because the your promise is resolving immediately instead of after 1000 ms. I think you meant this instead: `var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 1000));` – kYuZz May 31 '18 at 09:37
2

Actually, there's a bug in the example above. You're resolving the promise immediately, so setTimeout doesn't do anything. If you change that line to be

var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 1000));

then the behavior becomes as you describe:

> var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 1000));
undefined
> foo()
Promise {
  <pending>,
  domain: 
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }

To resolve this, you can use async/await to wrap foo, like this:

> var bar = async () => {
... var res = await foo();
... console.log(res);
... }

Running bar will now let you print (or inspect) the result as you expect:

> bar()
Promise {
  <pending>,
  domain: 
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }
> yay

The last line is printed after a second, unlike when you call foo directly.

Johan Persson
  • 1,875
  • 11
  • 11
1

Starting Node.js v10.0 you can use the options --experimental-repl-await to enable await in the REPL.

https://nodejs.org/api/cli.html#cli_experimental_repl_await

$> node --experimental-repl-await
> var foo = () => new Promise((resolve, reject) => setTimeout(resolve('yay'), 1000));
undefined
> await foo()
'yay'
Evgeny
  • 6,533
  • 5
  • 58
  • 64