Node.js

Node REPL (Read-Evaluate-Print-Loop)

Can use the Node REPL as in interactive environment.

$ node
> .help
> .exit

NODE_ENV=production node app // Sets Node environment from command

Introduction

Allows you to build scalable network applications using JavaScript on the server-side.  Runs on the V8 JavaScript runtime.

Node provides asynchronous or evented programming:

Blocking code:
Read file from filesystem, set equal to "contents"
Print contents Do something else

Non-blocking code:
Read file from file system
Whenever you're complete, print the contents // this is a callback Do Something else

For example, don’t use fssync (rather use fs) because fssync is not async which defeats the point of Node.

fs.readFile('/etc/hosts', function(err, contents) {  
  console.log(contents);
});

console.log('doing something else');  

Error-First Callbacks pattern

The "Error-First Callbacks" pattern applies to callbacks, not methods. In other words, a method on an object (unless it were intended to be a callback), would not use the Error-First Callback pattern. A function passed into the method as an argument, however, would probably implement the Error-Frist Callback pattern.

Callback Functions Are Closures

When we pass a callback function as an argument to another function, the callback is executed at some point inside the containing function’s body just as if the callback were defined in the containing function. This means the callback is a closure. Closures have access to the containing function’s scope, so the callback function can access the containing functions’ variables, and even the variables from the global scope.

Events

Many modules inherit from the EventEmitter constructor.  Objects in Node emit events (much like the DOM).

var EventEmitter = require('events').EventEmitter;  
var logger = new EventEmitter();

// on this 'error' event, run this callback
logger.on('error', function(message) {  
  console.log('Error: ', message);
});

logger.emit('error', 'Spilled Milk'); // logs 'Spilled Milk'  

Streams

See the stream-handbook.

There are 5 kinds of streams: readable, writable, transform, duplex, and "classic".

Streams and http

For example, request object is readable stream and response object is writable stream.  Read data from the request, and write data to the response (hence response.write):
http.createServer(function(request, response) { ... });

Request object is a Readable Stream that also inherits from EventEmitter.  Request object can communicate with other objects by firing events. request fires 'readable' and 'end' events.

Uploading a file with progress

curl --upload-file file.jpg http://localhost:8080;  
var http = require('http');  
var fs = require('fs');  
var file = fs.createReadStream('readme.md');  
var newFile = fs.createWriteStream('readme_copy.md');

http.createServer(function(request, response){  
    var fileBytes = request.headers['content-length']; // obtain file size from header
    var uploadedBytes = 0;

    // Using the readable event to keep track of current progress
    request.on('readable', function(){
        var chunk = null;
        while(null != (chunk = request.read())){
            uploadedBytes += chunk.length;
            var progress = (uploadedBytes / fileBytes) * 100;
            response.write('progress: ' + parseInt(progress, 10) + '%\n');
        }
    });

    file.pipe(newFile);

    request.on('end', function(){
        console.log('uploaded');
    });
}).listen(8080);

Pipe

.pipe() is just a function that takes a readable source stream src and hooks the output to a destination writable stream dst:
src.pipe(dst)

Readable

Readable streams produce data that can be fed into a writable, transform, or duplex stream by calling .pipe():
readableStream.pipe(dst)

var Readable = require('stream').Readable;  
var rs = new Readable;  

Writable

A writable stream is a stream you can .pipe() to but not from:
src.pipe(writableStream)

To write to a writable stream, just call .write(data) with the data you want to write:
process.stdout.write('beep boop\n')

Transform

Transform streams are a certain type of duplex stream (both readable and writable). The distinction is that in Transform streams, the output is in some way calculated from the input.

Duplex

Duplex streams are readable/writable and both ends of the stream engage in a two-way interaction, sending back and forth messages like a telephone.

Classic

Classic streams are the old interface that first appeared in node 0.4.

Whenever a stream has a "data" listener registered, it switches into "classic" mode and behaves according to the old API.

Note that whenever you register a "data" listener, you put the stream into compatability mode so you lose the benefits of the new streams2 api.

You should pretty much never register "data" and "end" handlers yourself anymore. If you need to interact with legacy streams, use libraries that you can .pipe() to instead where possible.

child_process

The most significant difference between childprocess.spawn and childprocess.exec is in what they return: spawn returns a stream and exec returns a buffer.

Modules & NPM

npm install -g [npm@latest](mailto:npm@latest) // update NPM globally
npm install[package] // —save (adds package to package.json)
npm install[package]@1.4.4 // use @ symbol to install specific version
npm update —save
npm help 7 config // config manual
npm ls

node -p "console.log(require('node-sass').info)" // see info of NPM module