Node.js excels at:
High availability API's, the asynchronous model reduces the amount of processor time being wasted in idle while waiting for external resources to be processed.
Pub-Sub systems like a chat server using WebSockets through Socket.io.
High availability Proxy services.
Develop desktop applications using Electron!
What Node isn't that good at:
Intensive processing on the server, if you have a task that you need to crunch, 9 times out of 10 there is a better tool around.
What you will learn#
By the end of this tutorial you will have a good grasp on the following:
How to use NPM, and understand how your Package.json file works
Understanding the basics of a Node.js application
Asynchronous programming using promises and the event loop
Building basic Node.js API using express
Using Node standard library, and the file system package
Try Catch error handling with Node
Prerequisites - What You Need To Know#
Step 0: Installing Node.js#
Node.js is available for most platforms.
If you are using brew on macOS you can install it as follows:
For Windows, Linux, macOS and other operating systems, you can download the Node binaries from here
Or you could use NodeSource to get your platform-specific binaries.
Step 1: Writing our Hello world with Node.js and understanding the basics of asynchronous programming.#
In an empty directory create a file named
app.js with a single line of code as follows
To run it, in your shell of preference just CD to the directory, and type:
And just as magic you will get an output in the console saying hello.
Let's use the Node.js standard File System module
fs, to write our hello world into a file:
Let's take a moment, to explore in-depth the lifeCycle of a Node application:
First Node.js loads into their respective scopes all the functions, including the Node internal functions like
require(), and user-defined functions like
helloWorld(), because of this you can use functions before they are declared as long as you are within the same scope, give it a try moving the call to
helloWorld()from line 9 to line 2.
Node Processes the provided input script, in this case,
app.js, each time that either on our code or any library we import an asynchronous call gets started, Node will allocate such call into the event loop.
After the input script is finished being processed (
app.jsin this case), then Node start the processing of the event loop and the asynchronous events allocated in it, in the following order of the following phases (described in the image in the right)
timers: this phase executes callbacks scheduled by
pending callbacks: executes I/O callbacks deferred to the next loop iteration.
idle, prepare: only used internally.
poll: retrieve new I/O events; execute I/O related callbacks (almost all with the exception of close callbacks, the ones scheduled by timers, and
setImmediate()); Node will block here when appropriate.
setImmediate()callbacks are invoked here.
close callbacks: some close callbacks, e.g.
Between each run of the event loop, Node.js checks if it is waiting for any asynchronous I/O or timers and shuts down cleanly if there are not any.
The entirety of the event loop is running within the same single thread!
Node.js is indeed single-threaded!
Following the Node application lifecycle, let's track the execution flow of the node application we just created, in the comments the "#" will outline the order of execution, please follow the # order:
If we decided to remove the await from line 13, the entire flow would change, the way
await works is that it transforms the current async function, into a promise.
If we removed the await from line 13, line 14 would just not wait for the fs.writeFile() operation to be finished, and process immediately, and instead of the rest of the function being stacked in the event loop, only the fs.writeFile() operation would be stacked.
Step 2: Writing our first API with Node.js Express.js#
With your install of Node.js, you will have the command line tool NPM, it is a package manager for Node, you can easily use it to download and install new modules, to import into your application.
For each Node application, you want to have a
package.json, this file will hold information about your project, Author details, version, how to execute it, custom NPM commands that you define.
package.json also contains a list of all your dependencies, that way if someone wants to use your application you only have to distribute the source, and using NPM all the dependencies can be easily installed.
To initialize the package.json file, run the following:
Follow the steps the command line, set the Author details, and the main entry point as index.js, the rest you can leave it as default.
To install a package using npm we do:
npm install <name of the package> we also add the --save flag to save our new added dependencies to our package.json file.
Now let's follow that and install our first npm module Express:
Express is a Fast, unopinionated, minimalist web framework for Node.js
Create a new file index.js, with the following source:
We run our web app, with the following command:
If you go to your localhost
http://localhost:3000/ you will get the response we coded:
A fun thing to consider, this time after we ran our application, it didn't automatically close! that's because of the following code:
app.listen() attaches a listener into the poll phase of the event loop, that listens for HTTP calls in the declared port, and unless we manually detach it, is going to be always up, and on each iteration of the event loop, is going to stay alive listening for new HTTP calls to invoke our callback function on each one.
Step 3: Expanding our API, to read and write to a file on each call#
Let's add a new route, to our API, that on each call uses
fs.readFile() to read into the file system, get the contents of the
helloworld.txt file, and send it back as the response of the request.
Also lets change, change the original / endpoint to return JSON instead of a plain text
Our API is looking pretty nice, but what would happen if you removed the
helloworld.txt and then attempted to call the /readFile API endpoint? Oh no, we got an error, and since the error is thrown on line 14, we never get to send a response back, so the browser would be waiting until the requests timeouts
The error in question would be:
(node:5288) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open 'helloworld2.txt'
(node:5288) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:5288) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process
with a non-zero exit code.
This error is caused by attempting to reading a nonexistent file with fs.readFile.
Step 3: Error Managing in Node done the right way.
You should always catch your errors!
We've been through a lot, within this short post, but by now you should have a well-rounded understanding of how a Node.js application works.
Have fun implementing your own API's!
Have fun and keep coding!
Check out the documentation of the modules we used in this post:
Getting Help (and Feedback)#
If you have any questions - or want feedback on your post - come join our community Discord. See you there!