Hack School Session 3

Welcome to Hack School session 3 (October 19, 2016). Up until now, we’ve been dealing with front-end development – HTML, CSS, JS. We could write the code and immediately see the results. However, today marks a turning point in our development. Things become a little bit more theoretical and abstract, and it’s harder to see how exactly these come together.

You can find the slides here

And let’s get started.

Download Node.js packet

For OS X/macOS

For Windows

If you already have Node.js installed, note that you’ll need some 6. x version of Node.js to have proper ES6 support.

Console emulators

The Command Line

The command line is a text interface to the computer. It accepts commands and prints out the output of the command onto the screen.

  • Commands are in the format [cmd][options] [arguments].
  • Everything you type is CasE sEnSitiVe!!!! When you name files and folders, try to avoid non-alphanumeric characters (special characters, spaces, etc.)
  • Options and arguments are additional (and sometime required) information.
  • Each option and argument is separated by a space. Think of them as passing arguments to a function.

Basic Commands — Mac/LINUS

  • cd [dir]change direcory
  • pwd — prints the curent (working ) directory
  • ls — list contents of current folder
  • mkdir [dir]make new directory
  • rm [file] — remove file
  • touch [file] — create an empty file
  • man [cmd]manual page: details about a command

Basic Commnads — Windows

  • cd [dir] — change direcory
  • cd — print the current directory
  • dir — list contents of current directory
  • md [dir]make a new directory
  • del [file]delete file

Options and Arguments – Mac/Linux

  • ls -l — long list


  • rm -r [file/dir]recursively remove. Can also remove folders and the files/folders inside them.


However, this could be very dangerous. You should think twice before using the rm -r command!

  • There are also special arguments such as ‘.’ and ‘..’ which meant “current folder”

and “parent folfer” respectively.

  • ’~’ means “home folder”

The Internet

Let’s talk about what the internet is. The internet is just a network of computers that are all trying to communicate with each other. The majority of communication is done over a protocol called HTTP. Every web site you’ve ever visited starts with the familiar http://. It tells the web browser that you want to make an HTTP request to a certain website.

Client, Server, ISP

There are three main roles in this schema. We have the client, whose role is generally to request information from a server. This is most commonly done through a web browser, like you normally do. When you ask the web browser to go to http://www.facebook.com, you’re a client. You’re making a request. In fact, any program on your computer that connects to the internet and requests information is a client. We’ll mainly be considering web browsers for Hack School, though. On the other end, we have the server, which is just a program on a computer whose job is to listen to HTTP requests and respond to them. There are a lot of programs that do this, and we’ll be using Node.js. If you’re ever heard of any of these other ones, there are examples of server frameworks. Finally, we have the ISP, which is the “middle man”. The ISP, like Comcast, AT&T, even UCLA, facilitates your communication with external web servers, like google and facebook.


  • A client connects to the internet through its router/modem. It sends an HTTP request, which is routed through the ISP. Now you might have typed www.google.com, but computers don’t know what that is. Computers can only identify other computers by their unique IP Address. So your request for www.google.com gets sent to the ISP, which looks up its IP Address, and then your request gets forwarded to the corresponding server. The server is listening for requests such as yours, and when it receives it, it generates a response and sends it back to you. This is definitely over-simplified, but an understanding of this is enough for our purposes.


  • Web Browsers are a client. So far we’ve used them to locally render HTML, CSS, and execute javascript, but as you know, Browsers can also do that for external websites, like google. The job of a web browser is to send an HTTP request, collect the server’s response, which will be in HTML, CSS, JS, maybe some images and videos, and render, format and display them. Take a look at the diagram above. It shows exactly what the web browser does.

  • a server is just a program that listens to HTTP requests and responds to them with content the client can understand. The diagram shows how a server works. It receives a request from a client, passes it to the server process, which does something to the request – it could involve reading files, executing scripts, making other network requests, accessing a database, WHATEVER it is, it does something, and generates a response for the client. That’s all a server does. Listen and respond.


  • What is a server for? Especially when we were able to create a website on our computers? Why do we need one? Servers are invaluable. Think about Google. Google is 2 billion lines of code. Not only would it be impossible to download it, but think about the massive amount of data Google has. Billions of websites and user data. You couldn’t possible store that on your computer, and your computer you probably take a year to search through it. Servers are dedicated and powerful. They let us generate dynamic, user-specific content (Gmail). They let us share information (Wikipedia).

    • HTTP is the standard by which computers communicate. It stands for Hypertext Transfer Protocol. An HTTP request consists of a method (we talk about it later) and a URL. The URL indicates which server to go to and which resource to ask for. Page, image, video, etc. The server parses the HTTP request and responds to it appropriately, however it was programmed to, with an HTTP response containing the requested information. Note: there are HTTP requests, and HTTP responses.


Node.js is not a language!

Node.js is:

  • a program that interprets and executes JavaScript on the server-side.
  • It does what the browser does, just on the server.
  • Both Node.js and the web browser execute JavaScript.
    • They speak the same language, but do different things!

Node.js is used to create stand-alone applications and write scripts, whereas the browser uses JavaScript to manipulate the document, generate dynamic content, and show animations. They’re different in the same way doctors are different from lawyers. Sure, both speak English, but that doesn’t mean they do the same thing. They both have their own specialized roles. To facilitate the extra roles Node.js has, it also has a standard library of available modules that let you interact with the file system, make network requests, and start other processes. Whereas the browser only has the standard objects and methods built into the language, like arrays and strings.

Running Node.js

Running a Node.js script is simple.

  1. Write your script and save it in a .js file.
  2. Open a terminal and navigate to the directory you saved it in using CD.
  3. Run the command “node” followed by a space followed by the file name you saved your script as. Let’s do an example.

Arrow functions – another way to define a function.

In order to leverage the power of Node.js, we need to learn a couple new JS constructs:

First up, objects.

Objects associate keys to values. Keys must be strings or numbers, and values can be anything including arrays and other objects. Here’s an example of a pet object.

let pet = {
        type: Dog,
        name: Doug,
        age: 5
    console.log(pet.name); // “Doug”

It has three properties, type, name, and age (OR anything you would like, really)!

Properties are in the format key : value . Each pair of key-value is separated by a comma. We can access these properties by doing object.properties;

We can also add properties and information to the object after we create it. There are two ways to add a property:

(1) One is to define a new property using the dot operator, like so.

 let pet = { type: Dog, name: Doug, age: 5 };
    pet.isVaccinated = true;// (1)using dot operator to define a new property

This adds the “isVaccinated” field to the object.

(2) The other way is like accessing an array, except you put the key in the square brackets and assign it to a value. This method is good when you are creating an object that doesn’t have a pre-defined set of keys. You can also access properties using both of these methods. If you try to access an undefined property, surprise, you get unsurprised!

pet[likesSquirrels] = true;
    console.log(pet.isVaccinated); // true
    console.log(pet[likesSquirrels]); // true
    console.log(pet.canFly); // undefined

Looping Through Objects – Alternate Notation

The only way to loop through all keys and values of an object is like this.

let grades = {A: 4.0, B: 3.0, C: 2.0, D: 1.0}; 
    for (let grade in grades)
        console.log(A(n)  +grade+  is a  +grades[grade]);

This is the syntax. We write:

for (let grade in grades)

meaning over grades, we iterate over its keys, which appears in grade. Then using the key, we can access the object to get the value, like you see in the console.log. This code iterates over a map of Letter Grades to GPA and prints out each association.

However, order is NOT guaranteed! Since an object is not ordered and can not be sorted, the order in which we iterator over the object is not defined.

Looping Through Arrays – Alternate Notation

For array, it’s the same, except we write “of” instead of “in.”

  for (let word of sentence)

Order is guaranteed!!!

The order is guaranteed to be from index 0 to n-1. This code concatenates each element (word) in the array to write out a sentence.

   let sentence = [This, is, a, sentence.];
    let str = “”;
    for (let word of sentence)
        str += word +  ;
    console.log(str); // “This is a sentence. ”

Node.js Event Loop

Node.js is Single-threaded, but event-based. It seems asynchronous to the programmer: this means that things might not happen in the order you think they’ll happen. This is due to the fact that Node.js uses an event loop to keep track of which tasks it should process when —But Node.js really is synchronous.

The event loop is a queue of events, functions, and tasks that Node.js is required to do. It could be a console.log, it could be a function call. it could be an HTTP request. A file could be done loading, etc. or just anything. Keep in mind that the event loop itself is synchronous – it is executed in the order that events are pushed into it. But it gives the illusion that its not.

For example, let’s says I have an event loop with a bunch of events. And I get to one that is “read this file”. I, as node.js, know that reading a file takes time, and could block me from processing other events. So I hand it off to another thread. When that thread finishes opening the file, it pushes an event back onto the loop telling me “HEY your file is loaded, do whatever you want with it”. And then whatever function I assigned to be responsible for handling it would be executed.


Well, this brings us to the topic of Callbacks – how we assign functions to handle events that might be executed indefinitely in the future.

Callbacks are functions passed as parameters to other functions. They typically fit the paradigm “… and when you’re done, do this”. Think back to the bakery example, where, I can say:””

​ Hey assistant. Get me some eggs.

​ And when you’re doen, crack the eggs

​ And when you’re doen, beat the eggs

​ And when you’re doen, mix it with flour, sugar, water, and brownie mix

​ And when you’re doen, pour it into a pan

​ And when you’re doen, put it into an oven. “

Each of these would be a callback passed to the next function. All the while, in between each of these tasks that the assistant does sequentially, because of the event loop, and the fact that there is going to be free time in between these tasks, I have execution time for other functions and statements.

Callbacks: setTimeout

setTimout is a built in function that runs another function after a specific amount of time, without blocking other statements from executing. An example:

setTimeout(() => {
}, 2000);

Here, we first print “A”. Then we set a timer to print “B” after 2000 milliseconds, or 2 seconds, and then we print “C”. A naïve approach to this would be to assume that this prints A, B, C. But NOTE. We set a TIMER in between A and C, but not necessarily printed it.

99% of the time, this will print A, C, B.

Here’s a more complicated example. After I explain this, let’s code it. 

function sum(a, b) { return a + b; }
function task(operation, a, b, callback) {
    setTimeout(() => {
        callback(operation(a, b));////We call this function. 
    }, 1000);
task(sum, 5, 3, result => {

First we define a function sum. It takes two numbers and returns its sum. Simple. Then we define a more complicated function that takes 4 arguments. The first is an arbitrary function. The second/third are two arbitrary arguments. And the last is a callback – what to do when this function is done. Inside this function, we set a timer for 1 second. That means this function is going to be asynchronous. Inside the timer, we call the callback with the value of applying the function fn to a and b. It just evaluates fn with arguments a, b and whatever its return value is, passes it to the callback, 1 second after the function is called.

We pass it the sum function, 5 and 3 for the middle two arguments, and then a callback arrow function that just console.logs whatever result it gets. What should the output be?

Answer: after one second, it should print 8. Let’s write the code ourselves. So, callbacks. Useful right? Don’t have to wait for a task to complete, just do the next action in a series of actions whenever its done. But wait.. what if we have something like this?


When you have to nest so many callbacks for a given task that it becomes impossible to read what you wrote.

a(input, resultFromA => {
    b(resultFromA, resultFromB => {
        c(resultFromB, resultFromC => {
            d(resultFromC, resultFromD => {
                e(resultFromD, resultFromE => {
                    console.log(Result from E, resultFromE);
                });		// nope nope nope
            });		// are we done yet?
        });		// which function is this?
    });		// what’s going on?
});		// where are we?

The real problem is the unnecessary indentation and the fact that its not clear what’s actually happening. ES6 Introduces a solution to this:

Promises. Promises are an object that wraps callbacks. They’re also better at handling errors, which you should always do. It flattens the structure of callbacks to be more intuitive, chaining a bunch of “then” function calls.

Here is how we declare a promise. Promises have a lot of useful methods, so it’s worth reading into independently. I’ll give you an overview, and a few more features when we get to the project.

let myPromise = new Promise(
    (fulfill, reject) => {
        // do something, when done:
        //   call fulfill for success
        //   call reject for error

myPromise.then(val => { /* success */ })
         .catch(err => { /* error */ });

A promise is an object that takes in a function as its only parameter. That function takes two functions as parameters, ‘fulfill’ denoting the function to call if the task that the promise was supposed to do was successful, and ‘reject’ denoting the function to call if there was an error. After we declare this object, we can chain it with “.then” and “.catch” calls. “.then” calls define what to do if the promise was fulfilled, that is, it provides the “callback” to the promise if it was successful. “.catch” defines what function to call when there’s an error – it handles errors that might arise in the promise and if the promise calls reject. You can have multiple “.then” clauses and they’ll execute in the order you chain them. Thus, it’s like callbacks, without the hell.

Mini Project!

Write a Node.js script that reads a file and calculates some statistics about it Download and unzip this to your project folder!


  • Count the total number of words
  • Find the average number of words per line
  • Find the top three most common words and the number of times they occur
  • Find all misspelled words


  • Given a dict.txt and file.txt

  • Given starting point script.jsNo empty lines, perfectly formatted text
    • No double-spacing, etc.
  • Only characters are alphabetic, space/newlineAll characters are lowercase

Why Node.js?

Phew, so that was a lot to take in. Take a moment to rewind. As you may have guessed, we’re going to use Node.js to build a web server. To explain how that works, we can view Node.js as a bakery.


  • A client comes to the bakery with an order of, say, 10 brownies.
  • The cashier accepts the order and passes it on to the baker. The baker knows how to make brownies, so he gets the recipe, and checks his ingredients and tools to make sure they’re enough for the job.
  • He might decide to ask his assistants to fetch him some ingredients or wash dishes, or other long running tasks, and while he waits, he’ll get started on the brownies.
  • When the assistants finish their tasks, the baker can pick up those tasks, and at the end of everything → fetching ingredients, mixing the batter, baking, and packaging, the baker gives the completed order to the cashier, who gives it to the client.


Now, if you know Node.js, you know I have described exactly what Node.js does:

  • The client is the web browser.
  • The cashier is a server.
  • The baker is the node.js process.
  • The recipes are the scripts your write.
  • The ingredients are your static files, html, css, images, etc.,

HTTP Requests and Responses

The tools, oven, fridge, etc. are the Node.js library, methods you can call, tools you can use. And the workers are the async threads we talked about.

Here is an example of each. Each request has a METHOD.


It tells the server what action the client wants to perform. In this case, it wants to GET an html page /doc/test.html. The next few lines are called HEADERS. HEADERS are information about the request. Optionally, if you have a POST request, you can also send some data in the request. For example, when you log into a website, it’s a POST request.

An HTTP RESPONSE is similar.


Instead of a method, it has a status: 200 means OK. Other common ones are 403: Unauthorized and 500: Internal Server Error. You’re guaranteed to encounter these at some point in your lives. The response also contains headers relaying information about the response, and then the response itself, called the BODY. So remember, a REQUEST has a METHOD, HEADERS, and optional BODY. A RESPONSE has a STATUS, HEADERS, and BODY.

HTTP Methods (“Verbs”)

Some of the different actions we can tell a server to do are GET, POST, PUT, DELETE. Each one of them is symbolic of something else. Use CRUD to remember it.

Remember CRUD: Create, Read, Update, Delete

POST: Create a resource

GET: Read a resource

PUT: Update a resource

DELETE: Delete a resource

The most common methods will be POST and GET.

Use POST to send data and GET to retrieve data.

We send a POST request if we want the server to CREATE a resource. GET to READ a resource. PUT to UPDATE a resource. DELETE to DELETE a resource. The most common ones are GET and POST. But remember, these are by convention. You should follow convention when writing your own server, but other servers may not necessarily follow convention, nor is it always appropriate.

Written on October 23, 2016