Say you want to write a little command line application. For example, a simple app that greets you, asks for your name, and then talks to you by your name. Here’s a sample session showing how your intended app looks like when used (user-typed input shown in red):
Right, right? So you start writing it and researching all things Node.js… soon enough, you find out that writing a line is actually done using
console.log(), great. But how do you read what the user types? Not easy to find, so more searching is needed…
…jeez, no trace of
readLine or anything similar on the Node.js library, by any reasonable name you can think of…
readLine is nowhere to be found…
readLine function for Rhino, but Rhino doesn’t seem too active, and mainly, it is not Node.js or compatible with it…
…and you keep searching…
Well, after some time, you end up picturing the answer: it turns out that Node.js uses an awesome “event-based model”, and this requires that any program that interacts with anything be written using “closures”, “callbacks”, “events” and what not. A monster. It is so bad that, to write the above sample app, you end up needing to read articles with titles like “Demystifying events in Node.js”. Node.js might be awesome, but if writing a simple app like the above needs a lot of demystifying, we may need to part ways…
(Note: I am not reproducing the code Node.js would need you to write the app above using just its out-the-box functionality – it’s “hardcore programming porn” and this blog would become NSFW.)
So all is lost, right? Nope! I applied some obscure programming superpowers called “coroutines” and built a good solution you can use easily! The best thing is that, fortunately, you can use it without needing to know what “coroutines” even means. Read on for the details.
Here is how you can use the solution I concocted:
1) I created a Node.js package called “nicl”, which stands for “Node.js Interactive Command Line”. I pronounce it like “nickel”. Here is nicl on github and here is nicl on npm. You don’t really need to check those links, just go ahead and install it from your command line:
2) Write code like the following for your little app (note the use of nicl):
3) You’re done! Run it from the command-line with “node main.js” or debug it inside NetBeans, even typing and interacting in the console window. It all works as expected!
For now, I’ve tested nicl to work nicely on OS X, for educational interactive apps, allowing simple line-wise input. It should also work in Windows and Linux, though. In the future it may gain more functionality such as raw “keypress” input, and become valid for production work – it may already be, but it just doesn’t have enough usage and testing to be considered such.
But meanwhile, enjoy!
SPILLING THE TECHNICAL GUTS
So yes, it’s true, Node.js doesn’t allow “sequential code”, and your program can’t block waiting for anything like a keypress — well, technically it can, but then all of Node.js blocks, even the part that detects keypresses, so the application hangs forever. Thus, out of the box, doing nearly anything in Node.js requires advanced computer science concepts like “closures”. Not simple. Not educational. Not for beginners. Bummer.
I dislike advanced compsci concepts with my daily coding as much as the next guy, but that doesn’t mean they aren’t handy sometimes. So the whole thing reminded me of a thing called “coroutines”, which allows you to “suspend” one calling function temporarily and then resume it when something is ready. So I Googled for “Node.js coroutines”…
…and a few minutes later I had found the awesome fibers package by Marc Laverdet, bringing coroutines to Node.js with the name of “fibers”. His main example showed how an application can seemingly “block” for a few seconds by calling a fiber-powered “sleep()” function, without actually blocking Node.js. If fibers could be used to wait for a few seconds without blocking input, it could most likely be used to wait for input itself…
…bang, it worked like a breeze. A few hours later, I had made nicl available on github and npm. The code is simple, have a look. Along the way, I learned how to release a package using npm, which is the best source code publishing experience I’ve ever had, and I’ve tried a few. Congrats node & npm folks. And I was even so fortunate to get Marc, the author of fibers, to check my code and suggest some improvement to it. So now I got some sort of blessing from the Node.js experts themselves. Thanks Marc!
When learning anything, the right progression of concepts and steps is the best guarantee for both faster and more solid learning. Specifically for programming, I believe that the best way for any newcomer to start is to first grasp the basic concepts, in isolation of the many complexities of real software. The first sessions should talk only about code execution, statements, variables, conditions, and loops. Only then, all the rest! And a beginner should also be as isolated from “magic boilerplate code” as possible. Thus, my best recipe to start learning to code is to write many varied command-line apps, initially without user interaction, and after that, just by asking the user to respond to simple prompts. Once you can write these things with one hand tied behind your back, it’s the moment to move on to real applications with a graphical user interface.
…but Node.js trickery was trying to get in the way of this great start…
…until nicl, which fixes that.
— Jon Beltran de Heredia, Barcelona, March 2016