1

I'm learning NodeJS. One thing I'm finding really annoying is when working with promises from an interactive console while debugging and/or just poking around at the interfaces of various libraries. The work flow is normally; call some library to do some work, wait for result, poke around at the result to see how it actually behaves and looks like.

For example (and just for example) I want to interactively inspect the image data structure returned from Jimp. I'm finding myself doing this from the console:

const Jimp = require('jimp');
const fs = require('fs');
let data = fs.readFileSync('path/to/my/test/images')
let image = null
Jimp.read(data).then((result, error) => { image = result; });
// Work with image here ...

This boiler plate gets annoying to write .. I think I missed a trick. Is there a more convenient way around this? A setting can set, or a library I can load or something?

I'd rather do this:

...
let image = await Jimp.read(data);
// Work with image here ...

But this gives "SyntaxError: await is only valid in async function". Or if not that, then maybe:

...
let image = resolveMe(Jimp.read(data))
// Work with image here ...

P.S. "async / await" is not an answer to this question. In order for an async function to be evaluated you have to give control back to the event loop, and you can't do that at an interactive prompt currently AFAIK.

spinkus
  • 7,694
  • 4
  • 38
  • 62
  • 1
    How about `let image = await Jimp.read(data);`? Would have to be inside an `async` function to be allowed. Basically, asynchronous code is just kind of a pain one line at a time in an interactive terminal. I just find it easier to write a 10 line program and run it in node.js. If I want to inspect things, I run it in the debugger and step through or set breakpoints. Or, sometimes, just inspect by inserting some `console.log()` statements and running it. – jfriend00 Jan 25 '20 at 04:11
  • Well, now your edit says you don't want to give control back to the event loop. NO asynchronous operation can complete without giving control back to the event loop so what you're asking for cannot be done. They finish their work by inserting an event into the event loop and that event cannot get processed until you return control back to the event loop. So, by definition, you have to. Javascript does not work the way you're asking it to, so therefore the console can't either. – jfriend00 Jan 25 '20 at 05:06
  • Your thinking too literally. Yes of course you have to give back control to the event loop. But there is no reason that can't be hidden from the user. I didn't say I "don't want" to give back control to the event loop. I said / meant that is how async functions get evald. – spinkus Jan 25 '20 at 05:13
  • Well, you're asking for stuff that doesn't work that way. Write a different interactive promise, I guess, that works the way you want. I don't think there's anything we can do to help. I never personally understood the attraction of the interactive console for anything other that really basic stuff anyway. I find it so much easier to just write a short program and run it, debug it, insert `console.log()` statements in it, edit it, run it again, etc... Way more efficient for my work than the prompt. – jfriend00 Jan 25 '20 at 05:15
  • "It doesn't work that way and there is nothing in the Node programmer toolkit that makes so ..." would be a perfectly acceptable answer. Maybe like you say it would be too hard to write a console wrapper that does work this way, but why reinvent the wheel if it's been done. Hence the Q. – spinkus Jan 25 '20 at 05:17
  • P.S. I edited Q again to show `await` doesn't work from the command prompt, but it would be cool if it could. – spinkus Jan 25 '20 at 05:27
  • Yes, that would be useful if `await` worked at the prompt. No conceptual reason why it couldn't, they just haven't done it. I'd suggest you learn how to use the debugger for variable inspection and put your code in a small file and run it in the debugger. You can then do line by line execution with breakpoints wherever you want. You can wrap it in an `async` function and use `await`, etc... – jfriend00 Jan 25 '20 at 05:34

3 Answers3

4

I stumbled on a SO answer for my Q. For node v12+ you can set the --experimental-repl-await option. Was right under my nose all along ... Summary:

Without:

$ node
Welcome to Node.js v12.18.1.
Type ".help" for more information.
> await Promise.resolve(7)
await Promise.resolve(7)
^^^^^
Uncaught SyntaxError: await is only valid in async function

With:

$ node --experimental-repl-await
Welcome to Node.js v12.18.1.
Type ".help" for more information.
> await Promise.resolve(7)
7
spinkus
  • 7,694
  • 4
  • 38
  • 62
0

That's what async- await is for. It lets you write async code in a way that looks like synchronous code, even though under the hood it is exactly the same as using Promises. Promises end up being very awkward with all the nesting of functions.

You can just write:

let image = await Jimp.read(data); 
// do something with image

And the only requirement is that the function you do it in has to be declared async. That means you need at the very least to have one function, you can't use await at the outermost level.

see sharper
  • 11,505
  • 8
  • 46
  • 65
  • But it has to be in an async function. You can't just write `let image = await Jimp.read(data); ` at the prompt. I almost qualified in the question: I'm not looking for async / await. – spinkus Jan 25 '20 at 04:29
  • Yes. I added a "P.S" please read. I know what async / await is - more or less. Try running `let image = await Jimp.read(data);` at the command prompt. – spinkus Jan 25 '20 at 04:36
  • Node uses async for ~everything. I thought there might be a monkey patch similar to what bluebird is to promises, for making stuff look synchronous at the console. – spinkus Jan 25 '20 at 04:47
0

Node.js doesn't really have a way to wait until an event, AFAICT. But in interactive mode, assuming you waited, all you care about is doing something with the result, so I tried to find convenient ways to get it.

The closest I can come up with is some helper like this:

Promise.prototype.a = function() {
    this
        .then(res => {
            Promise.res = res;
            console.log("async", res);
        })
        .catch(console.error)
}

Example usage:

Welcome to Node.js v12.2.0.
Type ".help" for more information.
> Promise.prototype.a = function() {
...     this
...         .then(res => {
.....           Promise.res = res;
.....           console.log("async", res);
.....       })
...         .catch(console.error)
... }
[Function]
> 
> function sleep(ms) {
...     return new Promise((resolve) => {
.....       setTimeout(resolve, ms);
.....   });
... }  
undefined
> 
> async function afterSleep(sec) {
...     await sleep(sec * 1000);
...     return 100;
... }
undefined
> afterSleep(2).a()
undefined
> async 100

> Promise.res
100

You still cannot wait for it to finish, but at least the result is available.

root
  • 5,528
  • 1
  • 7
  • 15