diff --git a/.gitignore b/.gitignore index bca51df..c32892a 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ jsconfig.json secrets.js .node_persist/ *.tgz +tmp/ \ No newline at end of file diff --git a/01 Introduction to ECMAScript 6/sentiment.js b/01 Introduction to ECMAScript 6/sentiment.js new file mode 100755 index 0000000..c13236c --- /dev/null +++ b/01 Introduction to ECMAScript 6/sentiment.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +'use strict' + +const sentiment = require('sentiment') +const minParam = 3 + +try { + console.log(process.argv) + if (process.argv.length < minParam) throw new Error('missing parameters') + const words = process.argv.slice(minParam-1).join(' ') + console.log(words) + const result = sentiment(words) + console.log(result) +} catch(err) { + console.log(err.message) +} diff --git a/01 Introduction to ECMAScript 6/tale.txt b/01 Introduction to ECMAScript 6/tale.txt new file mode 100644 index 0000000..7af82f3 --- /dev/null +++ b/01 Introduction to ECMAScript 6/tale.txt @@ -0,0 +1 @@ +It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair \ No newline at end of file diff --git a/01 Introduction to ECMAScript 6/todo.js b/01 Introduction to ECMAScript 6/todo.js old mode 100644 new mode 100755 index f5f852c..9fff1d8 --- a/01 Introduction to ECMAScript 6/todo.js +++ b/01 Introduction to ECMAScript 6/todo.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + 'use strict' const readline = require('readline-sync') diff --git a/book/01 Intro to NodeJS.md b/book/01 Intro to NodeJS.md index 6098df9..4a34d69 100644 --- a/book/01 Intro to NodeJS.md +++ b/book/01 Intro to NodeJS.md @@ -62,6 +62,16 @@ To uninstall a _local_ package you can use the `npm uninstall` subcommand and pa npm uninstall readline-sync ``` +#### 1.3 Useful Modules + +Although there are a lot of modules available through the package manager you will only need a few of these to complete the exercises in this book. + +- Request: an HTTP client written in JavaScript, for accessing web resources such as APIs +- Simple-Storage: a wrapper to store data in the filesystem +- Mongoose: a MongoDB object modeling tool. +- FS: a module giving direct access to the host file system, for reading and writing files +- Sentiment: a module that uses the AFINN-165 wordlist and Emoji Sentiment Ranking to perform sentiment analysis on arbitrary blocks of input text. + ## 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: @@ -233,6 +243,19 @@ list exit ``` +#### 2.4.1 Executing NodeJS Files + +There is an alternative way to execute a NodeJS script which works on Linux systems. it works because we have a _shebang_, otherwise known as a **processor directive** as the first line of our script. This tells the operating system where to find the command to run the script. +``` +#!/usr/bin/env node +``` +This tells the operating system to use the node command that appears in the environment path variable. You will also need to set the execute flag on the file. +``` +chmod +x todo.js +./todo.js +``` +The last line above tells the OS to run the `todo.js` file in the current directory. + ### 2.2 Test Your Knowledge @@ -273,36 +296,58 @@ Implement the `validateEmail()` function and thoroughly test it, you should avoi 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 +## 4 Passing Parameters on the Command Line -Learning advanced programming techniques -All programming done in ECMAScript 6 -Latest version of JavaScript -Significant update +You have probably seen some commands that take startup parameters. Each time you run a script, everything you type at the shell is made available through the process object which contains an `argv` array. -## Server-Side Scripting +This is useful since it means we can pass extra data to a script when we invoke it from the shell. We will be using this feature to pass in a sentence and measure its sentiment (positive or negative). +Open the script `sentiment.js` and make sure you understand how it works. -## NodeJS and ECMAScript 6 - -v6 supports most ECMAScript 6 features - -Block scoping: let, const -Promises -Arrow functions -Iterators and Generators +Try running the script without any extra parameters. +``` +$ node sentiment + [ '/Users/.../bin/node', + '/Users/.../sentiment.js' ] + missing parameters +``` +Notice that it prints out an array which contains two indexes corresponding to the _node command_ and the script name (sentiment.js). There is also a message that there are missing parameters. Where is this message coming from? +```javascript +const minParam = 3 +console.log(process.argv) +if (process.argv.length < minParam) { + throw new Error('missing parameters') +} +``` +In the code above you can see that the array printed to the shell is the contents of `process.argv`. The error was because the script expected an array of at least 3 indexes. -## Object Creation +Now let's run the command and pass it a sentence. +``` +node sentiment happy to meet you +$ node sentiment happy to meet you again + [ '/Users/.../bin/node', + '/Users/.../sentiment', + 'happy', + 'to', + 'meet', + 'you', + 'again' ] + happy to meet you again + { score: 3, + comparative: 0.6, + tokens: [ 'happy', 'to', 'meet', 'you', 'again' ], + words: [ 'happy' ], + positive: [ 'happy' ], + negative: [] + } +``` +So what's happened here? Well now the `process.argv` array contains the additional words we typed. because there were more than 2 indexes the error is not thrown. -The preferred way to create objects in JS is using an “object literal”: +Now we have some words to process we need to combine them into a single string. ```javascript -var empty_object = {} -var physicist = { - "first-name": "Albert", - "second-name": "Einstein" - "age": 135 -} +const words = process.argv.slice(minParam-1).join(' ') +console.log(words) ``` +The built-in `Array.slice()` method returns the section of array between the specified index and the end of the array. The `join()` method converts an array into a string using the parameter as separator. It is standard practice when programming in JavaScript to use _method chaining_ whereby several methods are called on the same data. +The final step is to pass this string to the sentiment tool which returns the sentiment of the sentence. diff --git a/book/02 Objects and Functions.md b/book/02 Objects and Functions.md index b151907..a807920 100644 --- a/book/02 Objects and Functions.md +++ b/book/02 Objects and Functions.md @@ -38,7 +38,7 @@ false ``` The preferred way to create objects in JS is using an “object literal”: -``` +```javascript var empty_object = {} var physicist = { "first-name": "Albert", @@ -49,7 +49,7 @@ var physicist = { Remember that the value can be any JS value. That includes other objects. In other words: objects can be nested. -``` +```javascript var flight = { airline: "BA", departure: { @@ -66,7 +66,7 @@ var flight = { Object values can be retrieved in two ways: Use [ ] around a string with the name to retrieve as a suffix to the object name: -``` +```javascript physicist["first-name"] // returns "Albert" flight["number"] // returns 882 ``` @@ -79,20 +79,20 @@ flight.departure.city // returns "Sydney" Undefined Values If you try to retrieve a nonexistent name from an object, JS returns undefined: -``` +```javascript physicist["middle-name"] // returns undefined flight.capacity // returns undefined ``` TIP: the OR operator `||` can be used to fill in “default” values: -``` +```javascript var middle = physicist["middle-name"] || "(none)" var capacity = flight.capacity || "unknown" ``` Undefined Objects If you try to retrieve a value from an object that is undefined, JS throws a TypeError exception: -``` +```javascript fakeObject["any-string"] // throw "TypeError" flight.capacity // returns undefined flight.capacity.minimum // throw "TypeError" @@ -102,7 +102,7 @@ Avoiding TypeError The AND operator && can be used to guard against this problem: -``` +```javascript flight.capacity // undefined flight.capacity.minimum // throw "TypeError" @@ -115,7 +115,7 @@ Setting object values at creation. Object values are set in two ways: During object creation, unless your object is empty {}: -``` +```javascript var employee = {name: "Colin"}; employee.name // returns "Colin" ``` @@ -123,7 +123,7 @@ employee.name // returns "Colin" Setting values by assignment. This sets a new value if the name does not already exist. Otherwise, it updates the existing value: -``` +```javascript physicist["middle-name"] = "Bob"; physicist["middle-name"] // returns "Bob" flight.arrival.city // returns "Los Angeles" @@ -134,14 +134,14 @@ flight.arrival.city.short // returns "LA" Call by reference. Objects are passed around in JS programs “by reference”. They are never copied. -``` +```javascript var a = {} var b = {} a.test = "hello" b.test // returns undefined ``` -``` +```javascript var a = {}; var b = a; a.test = "hello" @@ -149,7 +149,7 @@ b.test // returns "hello" ``` Example. -``` +```javascript var stooge = {first: "Jerome", second: "Howard"} var x = stooge; x.nickname = "Curly"; @@ -160,7 +160,7 @@ nick // returns "Curly" Function creation. This creates a function object using a function literal -``` +```javascript For example: function add(x, y) { var total = x + y @@ -172,7 +172,7 @@ Named functions. The function can use its own name to call itself Useful for manipulating tree structures -``` +```javascript var add = function(x, y) { var total = x + y return total @@ -197,7 +197,7 @@ Functions as object properties. Methods are functions stored as properties of objects. When a method is invoked, this is bound to that object. -``` +```javascript var myValueObject = { value: 0, increment: function(inc) { diff --git a/book/03 Asyncronous JavaScript.md b/book/03 Asyncronous JavaScript.md index 280e5c2..54c4736 100644 --- a/book/03 Asyncronous JavaScript.md +++ b/book/03 Asyncronous JavaScript.md @@ -8,46 +8,24 @@ Outcomes - Understand the JSON data format and know how to convert between it and JavaScript objects. - Understand Screen Scraping -## Command Line Options +## IO is Expensive -Used to pass data to a script at startup. -``` -node currency usd gbp -``` -In this example we have a command, a script and two command line options. - -Accessing Command Line Options - -Available through the process object +Waiting for IO to complete is big waste of resources +Three solutions: +synchronous +processes Apache +threads Node -Array called `argv[]` - -Contains entire instruction. -``` -node currency usd gbp -['node', 'currency', 'usd', 'gbp'] -``` +## NodeJS Threading Model -Useful modules. +NodeJS runs in a single thread +JavaScript supports lambda / callbacks +Callbacks run in their own threads +After callback thread is destroyed -Request: an HTTP client written in JavaScript, for accessing web resources such as APIs -Simple-Storage: a wrapper to store data in the filesystem -Nano: an ORM (database wrapper) for CouchDB -FS: a module giving direct access to the host file system, for reading and writing files - -Request module - -An HTTP client written in JavaScript - -Can be used by your scripts to access other HTTP resources on the web - -Very useful! -``` -var request = require('request') -``` Using Request.