Week 1
Introduction & Review

Getting Started 30 mins

Code Folder

I recommend that you create a folder to contain all of the code we will write in this class (weekly exercises and assignments). e.g. ~/code/mad9124

Remember, the ~ in the path above is an alias, or short-cut for your user directory. On macOS with a username of mckennr, this is usually /Users/mckennr. So, the full path above would be /Users/mckennr/code/mad9124.

What is node.js 30 mins

ECMAScript, JavaScript and Node.js — oh my!

Specification, implementation and interpreter — ah.

ECMAScript is the generalized specification for building a scripting language. JavaScript is an implementation of that specification, with some additional language features not yet finalized as part of the official specification. The ECMAScript Next support in Mozilla article at MDN Web Docs outlines these newer features.

By reading the ECMAScript specification, you learn how to create a scripting language. By reading the JavaScript documentation, you learn how to use a scripting language. -- Michael Aranda

Runtime Interpreter

JIT engine

JavaScript is not a pre-compiled language like Objective C or Swift. It is interpreted on the fly and converted to machine code at runtime. JavaScript was originally created for the browser and there are several runtime interpreters, sometimes called JavaScript engines.

  • Google Chrome has V8.
  • Firefox has SpiderMonkey.
  • MS Edge has Chromium V8 (was Chakra).
  • Safari uses JavaScriptCore (also called Nitro) as part of WebKit.

Of course, each of these may implement the various language features at different times (e.g. before the spec is finalized or sometime later). This ECMAScript compatibility table is a good resource. You may also want to consult the Can I Use website.

Runtime environment

This is the context in which the interpreter lives. Each environment provides additional objects to the JavaScript engine appropriate to its context.

runtime environments

Node.js is a non-browser runtime environment that uses Google Chrome's V8 engine at it's core. The V8 engine is also used in NativeScript and Electron for building native mobile apps and native desktop apps with JavaScript.

Like the browser runtime environment the core language implementation is provided by the V8 JavaScript engine. However, each environment provides access to certain environment specific objects.

For example the browser exposes a window object which does not exist in Node, and Node offers a fs (file system) object that does not exist in the browser.

What is Node.js good for?

Task automation in the command line environment.

Creating backend services for web and mobile applications requiring:

  • high scalability
  • data intensive operations
  • realtime / two way communication

Asynchronous architecture

TIP

async == non-blocking

sync == blocking

While JavaScript and by extension Node.js is technically a single threaded language, it does support asynchronous handing requests for external resources. That means that when fetching data from a database or calling another service's API, a Node application registers a listener for the eventual response and can go about processing other tasks until it is notified that the asynchronous response has been received.

For this reason, asynchronous code is also sometimes called non-blocking code. Conversely, synchronous code is sometimes called blocking code.

The mechanism used to manage this async hand-off and notification process is called the event loop which depends on Promises.

It is this asynchronous architecture that makes Node.js applications well suited for data access intensive workloads. On the other hand, tasks that are more in memory computationally intensive, like image processing, should not be done in the JavaScript main thread. This will be a blocking task until it completes. This is better handled by passing it off to another service and wait for the results.

The event loop

event loop diagram

Restaurant v.s. Bar analogy

At a restaurant, your server is like the Node.js main thread. They can take several orders in rapid succession and then go an dispatch those orders to other staff for asynchronous parallel processing. When your drinks are ready, the server is notified and delivers them to your table. Sometime later the food is ready and again your server is notified and then they deliver it to your table.

While your server is waiting for your order to be ready, they can respond to the next customer's request more quickly.

Contrast that with the typical experience at a bar. The bartender is like a synchronous PHP thread. There is one bartender and everyone is trying to get their attention. The bartender takes an order and all other customers wait while they prepare and then deliver that order. Only then can the next request be taken. So, if the first customer's order is more time consuming to make, everyone else is left waiting.

In the restaurant scenario, if one meal takes longer to make, others can be completed and delivered in parallel and the longer task will be delivered when it is ready without making everyone else wait.

Exercise 1-1 10 mins

  1. Install Node.js LTS version (12.14.0)
  • download the LTS (long term support) version from nodejs.org
  • run the installer and accept all defaults
  • open a terminal and verify that node.js is correctly installed
node --version
  1. Update the default package manager - NPM - to the latest version (6.13.4).
sudo npm install -g npm@latest

What did that just do? We told NPM to install a package named 'npm'. The -g flag told it to install as a globally available command – meaning that we can use it from the terminal in any folder without specifying the full path.

TIP

Installing a package with the -g or --global flags requires administrator privileges on macOS and linux, if you installed Node using its default installer. So, we need to prefix the command with sudo.

We also add the @latest suffix to the package name. NPM can install a specific version by using the @ directive after the package name e.g. package-name@5.4. In this case we used the label latest to get the most recent stable version.

Confirm the updated version

npm --version

Submit a single screenshot showing the installed version of both node and npm. e.g.

TIP

You can search from over 800,000 free code packages to use in your projects on npmjs.com

JavaScript review 30 mins

helloWorld.js

Code Editor

I am using VS Code. It is a simple to use code editor, but can be extended with plugins to speed-up repetitive tasks. I will try to point out some of the short-cuts that I use as we go.

Of course, you can use Atom, Sublime, Brackets, or whatever editor you are comfortable with.

In your code editor, go to your code folder for this class (e.g. ~/code/mad9124) and create a new scratch pad file that we can use to test some things out. I called mine helloWorld.js.

To start, create a simple JavaScript function that takes a message argument and writes that out to the console. Then invoke that function with the string 'Hello world!'.

function say(message) {
  console.log(message)
}

say('Hello world!')

OK, lets open a terminal so that we can run it. Be sure to change your working directory to the one where you just created the helloWorld.js file.

e.g.

cd ~/code/mad9124

TIP

VS Code has an integrated terminal that automatically opens in your current project folder. Choose "New Terminal" from the "Terminal" menu or use the keyboard short-cut, CTL`.

Use the node command to run this code in the terminal.

node helloWorld.js

Arrays of objects

When we are building backend services for applications, one of the most common tasks is manipulating collections of objects. Let's review some of the common methods for iterating over arrays and accessing the object properties.

Suppose that we had an array of student objects and each student had four properties: id, firstName, lastName and email. e.g.

const students = [
  {
    id: 1,
    firstName: 'Ella',
    lastName: 'Fitzgerald',
    email: 'fitzgee@algonquinlive.com'
  },
  {
    id: 2,
    firstName: 'Nina',
    lastName: 'Simone',
    email: 'simonen@algonquinlive.com'
  },
  {
    id: 3,
    firstName: 'Diana',
    lastName: 'Krall',
    email: 'kralld@algonquinlive.com'
  }
]

We could iterate over that array and write out hello with each student's name, one by one. JavaScript offers many ways to loop over an array, but in this case the simplest is to use the forEach method.

students.forEach(student => {
  say(`Hello ${student.firstName}`)
})

TIP

The example above uses the ES6+ arrow function syntax and template strings. This could have been written more conventionally as ...

students.forEach(function(student) {
  say('Hello ' + student.firstName)
})

This could also be written as ...

for (const student of students) {
  say(`Hello ${student.firstName}`)
}

Both looping methods produce exactly the same result. I find the first more readable, but you can decide which is more comfortable for you.

Object destructuring

Regardless of which looping method you choose, you'll notice that we access the firstName property of each student object using the standard JavaScript "dot notation" i.e. student.firstName.

It is often the case that we are only interested in a few properties of a given object and we may reference those properties multiple times in our code. In these cases it is more efficient to extract these properties to their own local variables within our code block.

In the past, you may have done something like this ...

students.forEach(student => {
  const firstName = student.firstName
  say(`Hello ${firstName}`)
})

We can now pull it out directly as a separate variable using a newer language feature called destructuring assignment.

students.forEach(({firstName}) => {
  say(`Hello ${firstName}`)
})

Extract objects from an array

Sometimes we are looking for a particular object or group of objects from an array. JavaScript has helpful built-in methods for these use cases.

If we want to print out just the student with an id of 3 we could use the find method.

const targetStudent = students.find(student => student.id === 3)
console.log(targetStudent)

The find method returns the first object matching the given criteria.

Or, if we want to count all of the students with an id less than 3, we could use the filter method.

const targetStudents = students.filter(student => student.id < 3)
console.log(targetStudents.length)

The filter method returns a new array with only the elements matching the given criteria. The length property of an array (like targetStudents) gives the count of elements in the array.

What is a JSON document?

So far we have been working with a small array hard coded into our program. In more realistic applications, we will be retrieving data from external storage sources, like JSON files or databases.

JSON stands for JavaScript Object Notation. It is a way to represent complex objects in a portable string format that can be easily shared between applications locally or over the network.

Let's covert our example students array to a JSON file called students.json. Notice that the property names need to enclosed in quotation marks.

[{
    "id": 1,
    "firstName": "Ella",
    "lastName": "Fitzgerald",
    "email": "fitzgee@algonquinlive.com"
  },
  {
    "id": 2,
    "firstName": "Nina",
    "lastName": "Simone",
    "email": "simonen@algonquinlive.com"
  },
  {
    "id": 3,
    "firstName": "Diana",
    "lastName": "Krall",
    "email": "kralld@algonquinlive.com"
  }
]

We can now load this into our helloWorld.js app using the Node.js require statement.

const students = require('./students.json')

Under the hood, Node is using the fs file system module and then the JSON.parse() method to read the file and automatically parse the JSON format into a JavaScript data structure ... in this case, an array of objects. We will explore the Node.js module system in more detail next week.

Your helloWorld.js file should now look similar to this.

const say = message => console.log(message)
const students = require('./students.json')

say('Hello world!')

students.forEach(({firstName}) => say(`Hello ${firstName}`))

Language Reference Resources

Exercise 1-2 40 mins

Accept the GitHub Classroom assignment called EX1-2 Hello Students.

Open a terminal window and navigate to your code folder for this course. e.g.

cd ~/code/mad9124

On GitHub.com in the starter repository created by GitHub Classroom, click the green [Clone or download] button to see the repo's URL. Click the clipboard icon to copy it.

Then use the git clone command in your terminal to create a local working copy of the repository on your laptop. The command will look something like this ... do not copy this one.

git clone https://github.com/MAD9124-W20/ex1-2-hello-students-mckennr.git

Change directory into the new project folder that was created by the git clone command. Following the example above my command would look like ex1-2-hello-students-mckennr. Yours will have your own username at the end. Then open that project folder with your code editor (I am using VS Code in this example) e.g.

cd ex1-2-hello-students-mckennr

code .

You should now have two files in your local project folder:

  • helloStudents.js
  • students.json

Requirements:

  1. read the JSON file into an array
  2. iterate over the array of students and print hello with their full names to the console
  3. print out the number of last names starting with the letter 'D'

The output in your console when you run it should look similar to this.

node helloStudents.js

Hello Ella Fitzgerald
Hello Nina Simone
Hello Diana Krall

Count of last names starting with D is 0

Hints

You will want to lookup the array filter method and the string charAt() method.

When finished, create a new git commit and then use git push to sync it up to GitHub. Submit the link to your GitHub repo on Brightspace.

For next week

Before next week's class, please read these additional online resources.

General

Review JavaScript fundamentals

Variables and Data Types

Functions

Quiz

There will be a short quiz next class. The questions could come from any of the material referenced above.

Last Updated: 1/5/2020, 5:05:07 PM