Sync, Async, and Creating Your First Server with Nodejs

Sync, Async, and Creating Your First Server with Nodejs

  • 2019-02-21 02:56 AM
  • 299

Welcome to Part I of **Learn Node.js **, a series created to help you easily understand Node.js

A new adventure has arrived! I will be taking you step by step from initial Node.js install to creating your first server, to customizing your responses, understanding streams and events, as well as using frameworks. Let’s begin.

Brigadier Fluffykins wants to make sure you’ve reviewed the basics of callbacks and promises. If not:

  • Watch this video & read this article on callbacks.
  • Watch this video & read this article on promises.

It’s ok if you don’t understanding everything right away. The important thing is that you are introduced to these concepts now. We want your brain to begin adjusting to the Node.js programming patterns you will implement throughout these lessons. Good luck and happy learning! :)

Today’s lesson will cover:

  • What Node.js is and what you can build with it.
  • Brief overview of how the web works(i.e. Client, Server relationship).
  • Downloading and installing Node.js on Mac/Windows/Linux.
  • What asynchronous/synchronous mean, and what non-blocking/blocking mean.
  • How to create your first server.

What is Node.js?

Node.js is an open source cross platform runtime environment that allows you to build scalable network applications on the server-side.

By runtime environment, I mean that inside Node.js is the _V8 JavaScript runtime _— the same one used (and developed by) the Google Chrome browser on the client-side. Using Node.js’s modules and libraries — explained later in this series — we have a way to:

  • Scale apps as traffic increases
  • Build chat rooms and other data-heavy apps
  • Directly manipulate database information
  • Access and shape the files in our system based on preference
  • Route requests (for website’s html/css/js pages) and monitor traffic
  • Have faster uploads and the ability to show the progress of those uploads
  • Customize our responses to these requests via routing and redirecting

Due to V8 and Node.js mostly being written in C and C++(even though many modules are written in JavaScript), Node.js is very fast. This is super important when you have an application that needs scaling.

Imagine thousands of users hitting your app, and thus requesting info from your server. What do you think will happen? You have no way of handling these requests, and even if you do, they may be synchronous (explained later). Users end up waiting in line behind thousands of other users for the necessary files to return. Loading speeds are slow, creating a poor user experience and causing you to lose business.

Scaling your app when traffic hits is one of the biggest challenges an app faces in the early stages.

Node.js allows you to operate a huge number of connections simultaneously and asynchronously — this basically means it allows for scalability. On top of this, you have libraries to help you customize the handling of these issues.

Client and Server: The Traditional Model

Before we continue I want to give a brief overview of how the web works via client and server. If you already understand this go ahead and skip this part.

When I say client, I mean anyone who is requesting information.

When I say server, I mean anyone who is processing a request and responding back with the necessary information.

For example, when you go to type in:

You are about to initiate several requests for the website’s HTML page, it’s CSS stylesheets, it’s JavaScript documents, and so on. You are asking or requesting their server to show you the page and all the documents associated with it.

When the website’s servers receives these requests, they respond with the HTML page, the CSS stylesheets, and whatever else you may need to view that page. This is the gist of it.

It’s important to note that anyone can be a client or a server. When you are creating an app locally you are in fact acting as a client and a server (such as localhost:3000). More on that later.

For now, let’s explore how Node.js handles these requests compared to the old-school model. We’ll use animations that Brigadier Fluffykins made for us. The orange is Brigadier Fluffykin’s request to his favorite website and the green is the response from the server. Slow and steady:

The traditional client-server model involves the client initializing a request first. Each request connection creates a new thread — a new process where code runs — thus taking up memory in your system. This eventually creates scalability issues due to memory running out or your server crashing due to an over flood of requests (high user traffic).

If you’re interested in diving deeper in how the client-server model works, I recommend exploring here.

Client and Server: With Node.js

With Node.js, both the client and server can initiate two-way connections allowing data to freely communicate between the two. Even though Node.js is single threaded — just like Javascript —and only one process happens at a time (explained later in the series), it ‘acts’ multi-threaded by processing requests via callbacks and promises. It’s thus able to support thousands of concurrent connections in an non-blocking/asynchronous manner.

Node.js can act as the client or the server or both. How awesome is that!?

As the server, a user visits your website and make requests (for HTML, CSS, and JavaScript files). Node.js receives these requests and sends a response (the HTML, CSS, and JavaScript files requested) and so on.

As a client, Node.js requests content from another site. For example, when a client wants to post something to Pinterest or Twitter from your site.

To use Node.js as a client you need to install the Request library (We’ll talk about installing modules and libraries for Node.js later in this series).

It’s important to realize that Node.js doesn’t do anything by itself. It’s not a web server. It’s just a runtime environment. If you want a web server, you bet your dilly da hoo ha that you need to write that server yourself young man (woman…child…cat…you get the point). You want to add information to your files? You gotta write that yourself too — Node.js doesn’t magically create this for you, but it sure adds a lot of great functionality you can play with. And Brigadier Bunny Fluffykins is going to teach you how! Yeah!

Downloading and Installing Node.js

  1. Open your command line terminal. If you don’t know how to find your command line, here are a few links that may help:

2. Next, make sure Git is up and running:

  • You can download it here.
  • Watch this 4 minute video intro on git.
  • Read this article if you still need help.

3. Download Node.js onto your system.

To check if you installed it, type in node -v in your command line, you should see the version number pop up:

Now that you have Node.js installed, you access the node command in your terminal, and type JavaScript code in your shell!

You can also execute code from a JavaScript file:

Let’s create a file called bunny.js in your code editor (such as Sublime, Brackets or Atom). Type in console.log(‘I will give Brigadier Fluffykins 20 carrot bits’) inside the file, or download this zip which includes this file as well as the next few files we need for the rest of the lesson.

Press ctrl + c inside the terminal for Mac twice to exit out of the node process (I believe it’s killall node for Windows — correct me if I’m wrong here).

Now find where your file is located. In my case, I moved to Desktop, then the folder where I saved the bunny.js file (nodestory). You may have it saved on your Desktop. Now in the shell type node bunny.js and VOILA! Your JavaScript shows up in the terminal! :)

Asynchronous & Synchronous Code

In order for Node.js to handle thousands of concurrent connections, it needs to handle them asynchronously, in a non-blocking way. What this means is you can have more than one action running at the same time, you saw this in the second animation.

Blocking — or synchronous — on the other hand, will run only one action at time. It will not allow a second action to run until it’s finished. When we sent a request for a file, we had to wait for the server to respond until we could send another request. This takes a really long time for Brigadier Fluffykins, and he was unhappy.

If you create code asynchronously, you can run actions in parallel. This can take less than half as much time as using a synchronous approach.

Although Node.js was purposefully created to be non-blocking, it allows developers the option to choose how they want their code run via changeable methods in their libraries. For example, Node.js has an appendFile method that can append something new to your file asynchronously or synchronously. Here’s another example:

Follow steps 1–5, or download this zip with files I’ve already created for you:

  1. First let’s create a folder called ‘nodestory’ .
  2. Create these 3 files: wishlist.html, bunnySync.js and bunnyAsync.js inside the folder.
  3. Open this folder in your code editor(Sublime, Brackets, Atom etc).
  4. In wishlist.html copy and paste this in:
Things I will pamper Brigadier Fluffykins with:
1. Carrot Bits
2. Lettuce Bits
3. Rasberry Bits
4. Toys
5. Hugs

NodeSeriesPart1_1.html

5. In bunnySync.js copy and paste this in:

// blocking / sync code:
// you have to require the file system(fs), Node.js's core module for it to work:
var fs = require('fs');

// First read the file 'wishlist.html' synchronously using the readFileSync method:
// We have to use the toString because it returns as a buffer.
// You can learn about buffers in the resources I provide at the end of this article.
var wishlist = fs.readFileSync('wishlist.html').toString();
//print the file
console.log(wishlist);
// Do another thing:
console.log('ALERT: Pounce owner!!!');

NodeSeriesPart1_2.js
Ok now run node bunnySync.js in your terminal:

Notice how our alert is printed in the same order as when we wrote the code? Now let’s try the same concept but asynchronously/non-blocking.

In bunnyAsync.js paste this in — make sure it’s the right file name:

// non-blocking / async code:
var fs = require('fs');

console.log('ALERT: Escape from bunny prison!');
// notice the method is called readFile not readFileSync.
fs.readFile('wishlist.html', function(err, wishlist) {
	if(err) throw err;
	console.log(wishlist.toString());
})
console.log('ALERT: Pounce owner!');
console.log('ALERT: Savagely devour rasberries!');

/* EXTRA: This method adds something new to your wishlist.html file.
Run 'node bunnyAsync.js' and see for yourself. Notice I leave this
method in blocking format otherwise, if I left in as appendFile (the
async version), the fs.readFile reads the wishlist.html file async and
then all the ALERT's print before the appendFile method is done
processing. Thus you won't see the change taking place until you call
'node bunnyAsync.js' in your terminal again.
*/
fs.appendFileSync('wishlist.html', '6. Shout "Happy with Async!!"', 'utf8');

NodeSeriesPart1_3.js

Ok now run node bunnyAsync.js in your terminal:

Notice how our alerts, no matter the order, all print before the file is fully read? Reading the file takes longer then using the console.log function, and thus our alerts are printed first. Once the file is read, it eventually prints.

Create Your First Server

It’s thaaaaaaat special time of year… to create your first server!

Woohoo! I am so excited for you! We’ll be going through several examples, so either create a file called server.js and paste this in:

var http = require('http'); // required for all steps.

// STEP #1 Basic server:
http.createServer(function(request,response) {
	response.writeHead(200); // Tell the client if response is good.
	response.write('My server worked!'); // the response body
	response.end(); // end the connection.
}).listen(3000); // you can change this to another port if you want, but then you would have to visit that port in the browser too.

// STEP #1.5 Basic Server Continued...
//var bunnyServer = http.createServer();
//bunnyServer.on('request', function(req, res) {
//	res.writeHead(200);
//	res.end('<html><body><h1>Bunny Server is live!<br /><img src="https://cdn.meme.am/instances/400x/55347780.jpg"></h1></body></html>'); 
//}).listen(3000);

NodeSeriesPart1_4.js

…or open the server.js file in the zipped folder I provided earlier.

Make sure that only the http and fs variables — as well as ‘STEP #1’ — are uncommented. Review the code and deliberate on what you think is happening before you continue reading.

As you may have noticed, along with modules and third-party libraries, Node.js also comes wth an extensive list of methods. You most likely won’t be using all of them — it really depends on what you’re building.

Now type node server.js in your terminal to start the server.

Go to your url header and type localhost:3000 to see the response you just sent:

Ok, what’s happening here?

For every request, you need a response. First, we respond to the client by setting the status code in the header to 200, meaning this website is OK, ready to go!

You can check the headers by clicking option + command + J in Chrome on a Mac, or right clicking and choosing inspect then clicking the Network tab (it’s one of the options next to the Console tab). If you don’t see anything under Network just hit refresh. Otherwise click the page and you will see under Headers the status code and what kind of requests the client made (in our case, “localhost:3000”). This is a GET request, since we want to get a file from a server.

Here’s what would happen if we set our headers to 404:

Try it out in your code and see if you can get a 404 status code.

Headers and status codes are an interesting topic by themselves, but I won’t go into that now. I have included resources in the end, if you’d like to research this more.

Next we have the response we want to send back to the client, or what the client will actually view on their page using the write method. Then we close the connection with the end method.

Lastly, we set up the port that our server will listen for requests. This can be 3000, 8080, or basically whatever you want. Just make sure you go to localhost:8080 if, for example, you’re using port 8080.

It’s a good practice to set the headers first before you set the response, especially because headers come before the body in the HTTP responses.

You just learned to create your first server! Pat yourself in the back, or slap yourself in the face — whatever works for you!

Let’s continue our adventure by building one of the more common forms you’ll see for HTTP servers. This is the same as what we just created, except there are some slight syntax differences which focus on events and event emitters (explained later in the series).

Comment out ‘STEP #1’ and uncomment ‘STEP #1.5’.

This is really important: before you do anything else, be aware that when you start a server then change something again in the file, the changes won’t be visible until you stop the server and start it again. There are libraries that will automatically restart the server for you upon detecting changes (like Nodemon), but don’t worry about setting that up right now.

For now, to stop the server manually go into your terminal and press control + C for Mac (again, I believe it’s killall node for Windows) then either press the up arrow to go through the previous commands you typed, or manually type in node server.js.

You should see this:

Notice that we can send some basic HTML inside the end method, thus sending a response and ending our connection at the same time. We can also store our server in a variable to make it more readable when we are using events such as request. It’s important to note that the request event is not the same as the Request third-party library. This confused me when I first learned Node.js, and I wouldn’t want you to go through the same thing. We’ll be talking about these in the next few lessons of the series.

Extra Resources

I implore you to go out and do some research. Make the most out of the time that you have. Here are a few places you can start:

Congrats! You’ve made it through Learn Node.js With Brigadier Fluffykins Part I! Now you’ll be able to explain the basics of Node.js as well as what you can build with it. You gained an intro on how async/non-blocking and sync/blocking code works, and the benefits that Node.js provides with async programming. Best of all, you were finally able to set up your very first server!

Wow. Seriously, great job. Brigadier Fluffykins commends your effort.

We will go deeper into these topics as well as others we’ve only scratched in the next few lessons. Thank you for reading and stay tuned.

Recommended Courses:

Learn Web Scraping with NodeJs in 2019 - The Crash Course

NodeJS & MEAN Stack - for Beginners - In Easy way!

End-to-End with Ionic4 & Parse/MongoDB on NodeJS/Express

NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)