An Introduction to Node.js
Node.js is an open source project that allow you to run JavaScript outside of the browser. As a consequence, Node has become very prevalent, and is a popular choice for backend projects.
What is Node.js?
Node.js is a JavaScript runtime environment that uses the V8 JavaScript engine, which also powers Google Chrome. Since Node.js uses V8, it benefits from all of the same optimizations that Chrome gets as well. Node.js is well suited for highly concurrent programs because it encourages writing programs using non-blocking paradigms.
Installation
Node can be installed for any platform on their website. If you're using Linux, you may also opt to use your package manager if it has a suitable version. The Windows installer will ask you to add Node to your path during installation. Make sure you do that so node
can be invoked on the command-line.
The Node.js REPL
If you type node
into a command-line (powershell, terminal, etc) you should get a >
prompt. Anything you type after this prompt will be parsed and executed as JavaScript. REPL, which stands for "read–eval–print loop", is an interactive programming environment. It reads your input code, parses and executes your code (evaluates), and prints the result. REPLs are useful for trying out small pieces of code, and even for addressing issues in a debugger.
Trying it out!
Try putting some JavaScript code into the REPL yourself! If node
was added to your path, then simply typing node
should start the REPL. You can input arbitrary expressions into the REPL, and they will get evaluated and return the result directly to you, without console.log()
!
Here is an example function that calculates the fibonacci number, provided that it can be pasted directly into the REPL:
function fibonacci(n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
fibonacci(10);
The result of any expression will be print to the console. Optionally, you can also assign the result to a variable for use later.
const result = fibonacci(10);
This will return undefined
in the REPL as statements don't return anything. You can input the name of the variable to check the value that got assigned. You don't need to call console.log()
to check the values of variables in the REPL.
Executing Node.js Files
If you want to keep the code for later use, store it in a file. The REPL should only be used for testing ideas and debugging. The fibonacci function can be added to a .js
file, and invoked on the command-line using node
to make it reusable.
fibonacci.js
function fibonacci(n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
const inputNumber = process.argv[2];
const result = fibonacci(inputNumber);
console.log(result);
Once saved, this program can be executed with a number of your choice: node fibonacci.js 15
. You may notice the call to process.argv
and wonder what it is. They are the command-line arguments passed into the program. Our number '15' is at index 2.
On my system, the contents of this variable include the following:
[ '/home/walter/.nvm/versions/node/v10.22.1/bin/node',
'/home/walter/fibonacci.js',
'40' ]
The first value is the node executable, the second is the path to the script, and the third includes the actual parameters passed into the program. The first 2 values will always be present when executing a Node.js script from a file.
Node Standard Library
Node.js has its own standard library that is not included in browsers. The standard library allows you to do many of the things expected of a scripting language, such as reading from and writing to files, opening sockets, and even building HTTP servers!
The standard library can be used by importing modules with require()
. Here's a simple example of using the os
module to determine which platform Node.js is running on:
const os = require('os');
console.log(os.platform()); // Prints your platform, in my case 'linux'.
The standard library is great, but it doesn't do everything. The Node.js community has created thousands of open source libraries and frameworks that you can get, free of charge, from npm. We'll cover how to use the npm package manager in a future post.
Concurrency and the Event Loop
Node.js uses an event loop to perform non-blocking I/O operations. JavaScript is single-threaded and can only execute your code in a single sequence, one instruction at a time. Worker threads allows you to have multi-threaded programs in JavaScript; however, the event loop is better suited for most concurrent operations such as downloading something over the network, making an API call or handling an event.
You may come across functions that make you pass callback functions or use async / await syntax to use the results. Those callbacks are usually executed after non-blocking I/O has completed, and it's the event loop that starts executing that code. You don't need to think about the event loop most of the time when you're writing JavaScript, but it's important to know that it exists as abusing it can impact performance negatively.
As described in the Node.js event loop documentation, each of the aforementioned steps are phases that are special in their own right. We won't dig into too much detail about each phase as we just care about the fundamentals, but the documentation describes them well if you're curious.
The main takeaway here is that concurrency, using the event loop, doesn't behave the same way multi-threading does. If you have a timer that gets stuck executing code for a long time, the rest of the program will stop until the callback on that timer finishes execution. The same applies in the reverse as well, so if you have code that blocks the main thread for a long time, timers may execute late.
A common concurrent operation one might do is schedule a timer to run some code after some time has passed. We don't want to sleep the main thread and cause execution to halt while we wait, so setTimeout()
can be used and will utilize the event loop.
The callback is the function that we pass into setTimeout()
. In this example we told it to wait 10 seconds, and did something else in the REPL while we waited. After the 10 seconds passed, the callback was executed. Timers that are created with setTimeout()
are executed during the timer phase of the event loop.
Conclusion
There's a lot more about Node.js that we'd like to discuss that can't fit in just one article, but hopefully these examples have given you a basic idea of what Node.js is. What really makes Node.js powerful is its community and diverse ecosystem of open source libraries and frameworks. We'll be covering more advanced topics in future articles, so stay tuned!