diff --git a/01 Introduction to ECMAScript 6/README.md b/01 Introduction to ECMAScript 6/README.md index 57b7395..4ebe1df 100644 --- a/01 Introduction to ECMAScript 6/README.md +++ b/01 Introduction to ECMAScript 6/README.md @@ -44,7 +44,7 @@ nvm install 7.9.0 node -v v7.9.0 ``` -We install the latest version and then set this as default. Finally, to check everything worked we check to see ehat version is installed. +We install the latest version and then set this as default. Finally, to check everything worked we check to see what version is installed. ## 2 Variables and Scope diff --git a/01 Introduction to ECMAScript 6/package.json b/01 Introduction to ECMAScript 6/package.json deleted file mode 100644 index 7c2e0f1..0000000 --- a/01 Introduction to ECMAScript 6/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "introduction", - "version": "1.0.0", - "description": "Simple examples showing JavaScript syntax", - "main": "contact.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Mark J Tyers", - "license": "ISC", - "dependencies": { - "readline-sync": "^1.2.21", - "sync-request": "^3.0.1" - } -} diff --git a/01 Introduction to ECMAScript 6/todo.js b/01 Introduction to ECMAScript 6/todo.js index 95afa1a..f5f852c 100644 --- a/01 Introduction to ECMAScript 6/todo.js +++ b/01 Introduction to ECMAScript 6/todo.js @@ -1,32 +1,20 @@ 'use strict' -/* the readline-sync module allows NodeJS to read input from the terminal. */ const readline = require('readline-sync') -/* Here we declare an empty array which will be used to store the todo list items. */ -var items = [] +const items = [] -/* the do-while loop has its exit condition at the end which means it always executes at least once. */ do { - /* We capture the text input by the user. This is then converted into a String and finally any _whitespace_ (newline characters, spaces, etc) are removed. */ - var input = String(readline.question('enter command: ')).trim() // try switching for a let... or a const... - /* The indexOf() function looks for the first ocurrance of the supplied string parameter or -1 if it is not found. Notice the use of === to compare the two values, this is a 'strict' comparison and should always be used instead of ==. It checks for equal values and equal type. */ + var input = String(readline.question('enter command: ')).trim() if (input.indexOf('add ') === 0) { - /* This time the indexOf() function is used to locate the first space character. */ - let space = input.indexOf(' ') - /* the substring() function returns the string after the specified position. This will include the space character and so the result is trimmed of any whitespace. */ - let item = input.substring(space).trim() - /* console.log() prints to the terminal. */ - console.log('adding "'+item+'"') - /* All arrays have a built-in push() function which appends an item to their end. */ + const space = input.indexOf(' ') + const item = input.substring(space).trim() + console.log(`adding "${item}"`) items.push(item) } if (input.indexOf('list') === 0) { - /* Here we use a for...next loop to interate through all the array indexes. The let keyword defines a variable with _block_ scope (more on this later). */ for (let i=0; i< items.length; i++) { - /* Here we reference the array index. */ - console.log(i+'. '+items[i]) + console.log(`${i}. ${items[i]}`) } } - /* the code will loop unless the input was _exit_. Notice the use of !== in the comparison instead of the more typical !=. This is a strict negating comparison. This means 'not equal and not equal type' */ } while (input !== 'exit') diff --git a/book/00 Introduction.md b/book/00 Introduction.md index d8366d7..d8f0384 100644 --- a/book/00 Introduction.md +++ b/book/00 Introduction.md @@ -3,6 +3,8 @@ This book covers advanced programming concepts using multiple paradigms. It is assumed that you are already comfortable writing and testing large amounts of code. +It is based on a long-running module at Coventry University called Web API Development. + By the end of this book you will: - Have learned cutting-edge JavaScript skills @@ -21,3 +23,72 @@ So why learn about developing web APIs? ## Book Structure The book is divided into three parts. In part (chapters 1-3) one we cover the principles behind the latest JavaScript (ECMA) language. In part two (chapters 4-6) we cover how to design RESTful APIs and how to build these. In the final part we cover a range of advanced topics to help you when you start writing more complex API. + +## How to Use This Book + +Each chapter is divided into two sections. Part 1 covers the core features which you will absolutely need to know whilst Part 2 covers the more advanced features that you will find useful. + +The learning revolves around reading and understanding code then testing your knowledge. Rather than printing out these scripts in their entirety, the book will highlight key concepts and give you a reference to the full code which is available on GitHub. + +If you are an experienced programmer feel free to skim over the part 1 content and focus on the advanced stuff in part 2. + +If you do not have lots of experience stick with the part 1 content then come back later, when you have more experience and tackle the content in part 2. + +### Cloning the Sample Code + +Whilst you could simply download the sample code from GitHub it is recommended that you clone this. The benefits are that as bugs are found and the exercise files improved, you can pull these changes into your local copy of the code. + +Assuming you are running a *NIX system you can clone the materials. This command will create a `nodejs/` directory in your `Documents/` directory containing all the sample code. +``` +git clone https://github.com/covcom/304CEM.git ~/Documents/nodejs +``` + +## Your System + +All the examples and exercises in this book are based on an Ubuntu-based system however if you are not using this platform you have several choices: + +1. You can take the plunge and install Ubuntu (either on its own or dual-book). There are plenty of online tutorials that cover this. +2. You can run Ubuntu as a virtual machine. One option is to use [VirtualBox](https://www.virtualbox.org) which is a free download and available for all major platforms. +3. Use a different flavour of Linux or Unix such as Fedora or MacOS (most of the commands will work just fine). +4. Stick with Windows and work around the issues. + +## Installing NodeJS + +Let's get started by installing the latest version of NodeJS. Whilst you would need to download and install a separate install for each version from the [NodeJS downloads page](https://nodejs.org/en/download/current/), because we are running a Linux distribution (you did read the previous section didn't you?) we can install the [Node Version Manager](https://github.com/creationix/nvm) and use this to install whatever version of Node we want. Lets fire up the Terminal. We need to use the cURL command to download the installation shell script and pipe it to the `bash` command to run it. +``` +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash +``` +The installation script has added a new path to your shell configuration and this needs to be loaded again. You have two choices, either log out then log in again or reload the shell using `source ~/.bashrc`. + +Now we can use this tool to check for the versions of NodeJS available. The latest version (7.10.0 at the time of writing) will be at the end of the list. +``` +nvm list-remote + ... + v7.0.0 + v7.1.0 + v7.2.0 + ... + v7.10.0 +``` +Finally we can install the current (latest) version (v7.10.0) at the time of writing. +``` +nvm install 7.10.0 + Downloading https://nodejs.org/dist/v7.10.0/node-v7.2.0-linux-x64.tar.xz... + ######################################################################## 100.0% + Now using node v7.10.0 (npm v3.10.9) + default -> 7.10.0 (-> v7.10.0) +``` +Finally we can check which version is installed. +``` +node -v + v7.10.0 +``` + +## Installing a Code Editor + +There are plenty of choices when it comes to editors. The examples in this book will use the [Visual Studio Code](https://code.visualstudio.com) editor which is available for all major platforms. If you are looking at other editors then choose one that supports JavaScript and plugins. + +Note that you may need to update the configuration database before Visual Studio Code will install. +``` +sudo apt-get update && sudo apt-get install libgconf2-4 +``` \ No newline at end of file diff --git a/book/01 Intro to NodeJS.md b/book/01 Intro to NodeJS.md index e16828f..6098df9 100644 --- a/book/01 Intro to NodeJS.md +++ b/book/01 Intro to NodeJS.md @@ -1,44 +1,289 @@ -## Programming Language +# Introduction to NodeJS -Learning advanced programming techniques -All programming done in ECMAScript 6 -Latest version of JavaScript -Significant update +In this chapter we will begin learning about programming in NodeJS. Note that we will only be covering the parts of the language that relate directly to building our APIs, there are lots of books that cover the language in more depth. -## Server-Side Scripting +NodeJS is based on the JavaScript language which is used extensively in the browser to handle such tasks as form validation and animations. The latest version of the language (known as ECMA6) is not fully supported by the different browsers and, as a result, it is not recommended that you use the more up to date features. + +NodeJS is built on Chrome's V8 JavaScript engine which powers the latest version of the Chrome web browser and supports the majority of the latest ECMA6 features. It has been modified to allow it to run on a server. + +Because our scripts will run on the server on which we have installed a known version of the ECMA6 runtime, we can guarantee that our scripts will run correctly which means we can focus on teaching the absolute latest programming concepts and features. + +## 1 Benefits of NodeJS + +There are a lot of languages that can be used to write server-side script ranging from **Perl**, one of the earliest _CGI Script_ languages through **PHP**, one of most popular languages and through to **Java** and **C#**. So why is NodeJS becoming so popular in recent years (and why have I chosen it for this book? + +The first, and most obvious answer, is that, as a web developer, you are going to have to learn JavaScript anyway because its the only language that will run natively in a web browser so why not use the same language for both client and server? + +The second benefit, and one we will return to in chapter 3, is that, unlike other scripting languages which create a new _process_ for each connected user, NodeJS runs a single process shared between _all_ users. Since processes are expensive in computing resources it means that a NodeJS deployment is far more scalable. In chapter 3 we will learn how it handles concurrency through the use of threads. + +It is assumed that you can already program in a modern language such as Python or Java and have had exposure to 'old school' JavaScript. This chapter will therefore expose you to some of key new features of the language and their impact on the way you program. + +Make sure you have cloned the repository containing the sample code by following the instructions in the previous chapter. + +## 1 Node Packages + +NodeJS can be extended through the use of **packages** and these are installed using the **Node Package Manager**. This was installed when we installed Node. +``` +$ npm -v + 4.2.10 +``` + +One of the most valuable features of NodeJS is its package manager which allows you to install additional functionality in the form of _packages_. There are thousands of these to choose from and, in a later chapter, you will be shown how you can publish your own packages. + +In the examples in this chapter we will be using a _node package_ called `readline-sync` to capture user input. The documentation for all published packages can be found on https://www.npmjs.com so open this page and search for the documentation for `readline-sync`. + +### 1.1 Installing Packages + +Packages can be installed either locally or globally. + +- Local packages are installed in a `node_modules/` directory within the directory containing the NodeJS scripts. This is the way we install most of the modules. These are only available within that directory. +- Global packages on the other hand are installed system-wide and can be accessed by all the scripts. Normally these need to be installed using root privileges. We will be using global packages in a later chapter. + +Open the Terminal and navigate to the `nodejs/` directory containing the sample code. If you are using _Visual Studio Code_ you can use `File > Open` to open the `nodejs/` directory then open the **Integrated Terminal**, accessed from the **View** menu, this will automatically open in the project root. + +Navigate to the `01\ Introduction\ to\ NodeJS/` directory and then install the package. +``` +npm install readline-sync +``` +This will create a new directory called `node_modules/` which will contains the scripts from the `readline-sync/` package plus any dependencies. + +### 1.2 Listing and Uninstalling Packages + +There are two ways to see what packages are currently installed. The quickest is to locate the `node_modules/` directory. Alternatively you can use the `npm ls` subcommand which will print this information to the shell. +``` +$ npm ls +/Users/.../01 Introduction to ECMAScript 6 +└── readline-sync@1.4.7 +``` + +To uninstall a _local_ package you can use the `npm uninstall` subcommand and pass it the name of the package you want to uninstall, this will uninstall both the named package and any dependencies installed by it. +``` +npm uninstall readline-sync +``` + +## 2 Variables and Scope + +If you have ever worked with JavaScript you will have declared variables with the `var` keyword. This creates a _hoisted function-scoped_ variable which has several issues: + +- The variable is _function-scoped_ meaning that it is only visible inside the enclosing _function_. This means that if you want to hide this from the rest of your code (considered good practice) you need to keep it inside a function which is tricky to implement. +- The variable is also _hoisted_ which means that it can be accessed before the line on which it is declared! Effectively all variable declarations are moved to the top of the function block. This can have some nasty side effects. + +Until the release of ECMA6, programmers in JavaScript have had to work with these issues but the release of ECMA6 provided two more options and the use of `var` is now deprecated and should no longer be used. + + + +### 2.1 Block-Level Variables + +Now we can declare _block-level_ variables using the [let](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let) keyword. These behave much like variables in other languages such as Python or Java in that they are only visible in the block they are declared in (such as a loop or branch). + +### 2.2 Block-Level Constants + +Until ECMA6, you could not declare _immutable variables_ (otherwise known as constants). ECMA introduced the [const](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) keyword that can be used to declare block-level constants. + +### 2.3 Worked Example + +Now we have learned some theory it's time to see this in practice. Load up the `todo.js` script and read through it to understand how it works. There are lots of code comments to assist you. + +#### 2.3.1 Strict Mode + +Notice the first line contains a **Directive**. This is a feature from ECMA5 telling the JavaScript runtime to run the script in [strict mode](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Strict_mode). +```javascript +'use strict' +``` + +This: + +- Prevents the declaration of global variables. +- Exceptions are thrown rather than the script fail silently. +- Prevents duplicate property and parameter names (more on this later). + +For the above reasone + +Use the **terminal** to run the script by entering ` node todo.js`. Once running you can use the `add` command to add new items to the list and the `list` command to print out the list items. The final command will terminate the application. + +#### 2.3.2 Importing a Package or Module + +Since we will be using the functionality in the `readline-sync` package it needs to be imported using the `require` function. +```javascript +const readline = require('readline-sync') +``` +This can be used to import an installed package (as we are doing here) but can also be used to import other scripts we have created locally (this is covered in a later chapter). + +#### 2.3.3 Conditionals + +JavaScript includes the standard set of conditionals (if, if...else and switch) and the syntax is similar to other modern programming languages. The `todo.js` script makes use of a number of `if` statements to identify which option the user has entered, for example: +```javascript +if (input.indexOf('list') === 0) { + // the user has chosen the 'list' command. +} +``` +Later in this chapter you will be required to implement a `switch` conditional. These share the same syntax as most modern languages and require a `break` command to exit and take an optional `default` clause. +```javascript +const name = String(readline.question('your name: ')).trim() +switch(name) { + case 'John': + console.log('your name is John') + break + case 'Jane': + console.log('your name is Jane') + break + default: + console.log('unknown name') +} +``` + +#### 2.3.4 Loops + +Javascript also supports a wide number of loop constructs: + +- for +- while...do +- do while + +In the `todo.js` script you can see the run-loop has been implemented using a do...while loop. +```javascript +do { + // this is the run loop +} while (input !== 'exit') +``` +It also uses a traditional for loop with loop variable using a syntax similar to C++ and Java. It uses the Array `length` property to iterate through it. +```javascript +for (let i=0; i< items.length; i++) { + /* Here we reference the array index. */ + console.log(`${i}. ${items[i]}`) + } +``` + +#### 2.3.5 Strings -Communicate with file system -Databases +In JavaScript, all strings are objects and have a number of useful methods. In the `todo.js` example there is a line: +```javascript +const input = String(readline.question('enter command: ')).trim() +``` +1. The `String()` function takes the expression entered by the user and turns it into a `String object` +2. we remove any whitespace from the beginning and end of the user-entered string by calling the `trim()` method which is part of the String object. -No web browser in sight... +Later in the script we use another method `indexOf()` which returns the index of the first instance of the string parameter. This is used in an `if` statement to see what is at the start of the string. +```javascript +if (input.indexOf('add ') === 0) { + // the string starts with 'add ' +} +``` +Notice the use of `===` rather then the standard `==` [equality operator](https://developer.mozilla.org/en/docs/Web/JavaScript/Equality_comparisons_and_sameness). JavaScript supports both but they work in slightly different ways: -## IO is Expensive +- `===` is used for **Strict Equality Comparison** where the result is only `true` if both the value and data types match. This is the preferred choice in **all** situations. +- `==` is used for **Abstract Equality Comparison** and works by automatically converting both values to a common type. This can lead to obscure bugs and so should be avoided. -Waiting for IO to complete is big waste of resources -Three solutions: -synchronous -processes Apache -threads Node +The script uses a second `if` statement locate the index of the first space in a string to allow it to be split into two. The `substring()` method takes a parameter and returns the string after the supplied index. We need to use `trim()` to remove the space from the start. +```javascript +const space = input.indexOf(' ') +const item = input.substring(space).trim() +``` -## NodeJS +It's worth taking a few moments to learn about some of the useful [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) methods. + +#### 2.3.6 String Concatenation + +There are two ways to concatenate (join) strings. Prior to ECMA6 the `+` operator was used to join string literals and string variables. +```javascript +const name = 'John Doe' +console.log('my name is '+ name) +``` +ECMA6 introduces the concept of [template literals](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals) which are string literals allowing embedded expressions. The string literal needs to be encased in backticks rather than quotes and the variables enclosed in `${}`. The previous example would look line this. +```javascript +const name = 'John Doe' +console.log(`my name is ${name}`) +``` +By using _template literals_ your strings become much easier to read and so you should get into the habit of always using these. -Node is a server-side runtime engine for JavaScript -A container that lets you run JavaScript without a browser -You can run programs written entirely in JavaScript to run the "server side" of web applications +#### 2.3.7 Arrays -## Why is this Good? +Our `todo.js` script declares an array near the start to hold the items in our todo list. Notice that the array is declared as _immutable_ using the `const` keyword. -Often the web client will be written in JavaScript too -Less to learn -Not limited to web servers, it can do anything any other language can do (e.g. numerical modelling, statistics, image processing, etc.). +```javascript +const items = [] +``` +Arrays are _objects_ and have a number of built-in methods. Later in the script we use the built-in `push()` method to add an element to the end of the array. You should take a moment to look through the list of built-in [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) methods and familiarise yourself with them. +```javascript +items.push(item) +``` -## NodeJS Threading Model +### 2.4 Running a NodeJS Script + +Now you have an understanding of the code features used in the script it is time to run it. Unlike client-side JavaScript, you don't run NodeJS scripts in a web browser, instead you need to run them using the **Terminal**. + +To run your script you need to run the `node` command and pass it the name of your script. You don't need to pass the file extension, so these commands are equivalent: +``` +node todo +node todo.js +``` +When the script is running you will be prompted to enter a command. Try adding three items and listing them all. Finally typing exit to return to the shell prompt: +``` +enter command: add bread +adding "bread" +enter command: add butter +adding "butter" +enter command: add cheese +adding "cheese" +list +0. bread +1. butter +3. cheese +exit +``` + + +### 2.2 Test Your Knowledge + +Now you are familiar with the basics of the ECMA6 language its time to put this to the test. Make sure you successfully complete all six tasks before continuing to the next section. + +1. locate the `input` variable declaration (just inside the `do` loop) + - define it as a block-scoped variable by replacing the `var` with `let`, what effect does this have? + - modify the script so that it still works (keep the `let` variable declaration). + - substitute a constant by substituting `const` for `let`, what effect does this have? + +2. the array at the top of the script is defined using `var`. What happens if you make this immutable (use `const`)? +3. Items are added to the array using its `push()` method. + - substute the [unshift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift) method. How does this change the script? +4. modify the code to prevent duplicate items being added. You will need to use the [`Array.indexOf()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) method. +5. create a **remove** option so an item such as *cheese* can be removed using the syntax `remove cheese`. You may need to use the [`Array.splice()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) method. +6. The current version is case sensitive. Modify the code so that items are converted to lowercase before being added or searched for. You will need to use the [`String.toLowerCase()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase) method. + +## 3 Exception Handling + +When JavaScript executes code errors and exceptions may occur. These may be due to incorrect user input or a broken network connection for example. JavaScript includes a rich set of tools for handling these, based on the [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object. + +1. Errors are serious problems that normally mean the application will terminate +2. Exceptions on the other hand are problems that can be handled by the program logic and thus prevent the application from terminating. In this task we will be focussing on _exception handling_. + +Open the `contact.js` script and study it carefully, as before, the code includes detailed comments to explain how it works. + +1. All code that could throw an exception _must_ be in a `try{}` block. +2. If an exception is _thrown_ the execution moves to the `catch{}` block. + - the error object thrown will be passed as the parameter. + - the error object contains three properties: the name of the error, the message passed and the stack trace. + - the _stack trace_ is a list of the method calls that the application was in the middle of when an Exception was thrown and can help identify some of the more insidious errors. You should learn to read and understand what information it contains. + +### 3.1 Test Your Knowledge + +Implement the `validateEmail()` function and thoroughly test it, you should avoid using regular expressions at this stage: + +1. Check that the string is at least 5 character long +2. Check that there is a `@` character and that it is not at the start of the string (HINT: use the [indexOf](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf) String prototype method. +3. Check that there is a period (.) character after the `@` character but before the end of the string. + +---------------------------------------------------------- + +## Programming Language + +Learning advanced programming techniques +All programming done in ECMAScript 6 +Latest version of JavaScript +Significant update + +## Server-Side Scripting -NodeJS runs in a single thread -JavaScript supports lambda / callbacks -Callbacks run in their own threads -After callback thread is destroyed ## NodeJS and ECMAScript 6 @@ -52,7 +297,7 @@ Iterators and Generators ## Object Creation The preferred way to create objects in JS is using an “object literal”: -``` +```javascript var empty_object = {} var physicist = { "first-name": "Albert", @@ -60,3 +305,4 @@ var physicist = { "age": 135 } ``` +