What is a REPL?

An interactive REPL is great when trying out ideas, verifying that an expression is syntactically correct, etc. just type and the code is evaluated every time you press return

Node.js comes with a REPL built-in. Start it by typing node without a second argument at the command-line.

$ node
> var foo = 2;
2
> var bar = foo + 3;
5

Assignment works like you would expect, but each evaluation’s resulting value is also printed on the screen.

You can do functions too. Anything beyond one-liners are quite unergonomic to deal with though.

> function add(a, b) { return a + b }

> add(foo, bar)
7

ES6 double arrow syntax can help reducing the visual overhead a little bit

> var subtr = (a, b) => b - a;

> subtr(foo, bar)
3

Modern ES6 code tends to use either const or let when declaring variables and the old-school var declaration is seldom used due to its lack of strictness and greater room for unpredictability. In the REPL, where tend you play around with ideas more often than writing large chunks of structured code, var can be more convenient, as it allows you to press the up arrow a few times and re-execute a previous variable declatation. If you try to do that with let or const you have to rename the variable every time, wheras when using multiple declarations of var, the last declaration wins.

async await in Node.js REPL

But how to deal with asynchronous calls in the REPL?

> await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('hi after await');
await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('hi after await');
^^^^^

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

To wrap the expression in an async function and call it straight away works…

but it gets tedious, error prone and does not feel REPL-friendly:

> (async () => { await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('hi after await'); })();
Promise { <pending> }
> hi after await

Also, you don’t know whether it is still awaiting something or not and your next prompt can suddenly get interrupted with late stuff from earlier prompts.

In Node.js 10 and later however, you can use a CLI flag to enable support for await even in the outer context.

node --experimental-repl-await

> await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('hi after await');
hi after await
undefined

That’s a lot nicer!


Update: as of Node.js 16.6, --experimental-repl-await is on by default.

Hopefully that makes the REPL more intuitive straight out of the box.




sponsor

Need private photo sharing that's not tied up in the social media circus? Photoroll is a good way to share photos with your clients.
Or privately gather media from participants of weddings and other small to medium-sized events.