Node.js Video Tutorial by Ryan Dahl

By Xah Lee. Date: . Last updated: .

Windows is very important… just like PHP. —Ryan Dahl

This is a intro to Node.js by its creator Ryan Dahl. It is a very good. You should watch it. I added annotations and his code snippets, so you can actually try it out.

Introduction to Node.js with Ryan Dahl
Mar 16, 2011
InfoQ

The video is one hour long, but to really understand, you'll need to do hands-on coding. It'll take 2 to 3 hours. Also, you do need to have experience with JavaScript. [see Xah JavaScript Tutorial]

Here is the code snippets shown in the video. I've run and tested them.

The “process” Object

process is a global object in Node. Here's some use of process:

// some example use of process object

process.stdout.write("rabbit\n"); // prints rabbit

console.log(process.version);   // v0.10.24

console.log(process.env);       // prints out environment variables in JSON format

console.log(process.pid);       // 9512 process id

// force exit
process.exit()

Save the file, for example as xyz.js, then run it in terminal node xyz.js.

you can use process to get node version, environment variable, process id, command line arguments, read/write to {stdin, stdout, stderr}, etc. process

Asynchronous Hello World

setTimeout and setInterval are used to demonstrate asynchronous nature of JavaScript and Node.

// after 2 secs, print
setTimeout( function () {console.log("two"); }, 2000);

console.log("one");

// prints “one” first, then “two”

The point is that the setTimeout is not sleep. The program doesn't halt. For languages that have “sleep”, when sleep is called, the program halts and doesn't do anything else. JavaScript doesn't have “sleep”. This is the async nature of JavaScript, and node.js takes this idea further.

// print every 2 secs
setInterval( function () {console.log("world"); }, 2000);

console.log("hello");

Note: Node's setTimeout and setInterval are based on the same functions implemented in web browsers. These are technically not part of the JavaScript language, nor in DOM. They are functions in Browser, called Browser Object Model. setTimeout(cb, ms) [see Browser Window Object]

In node.js, “everything” is async (aka non-blocking), similar to the setTimeout and setInterval. Typically, a function that do things such as {reading file, handle request, query database}, takes a function f as the last parameter, and this function f will be called when it is ready. f is called “callback” function.

For example, to read a file in most lang, you do “myContent = open(path)”, then you do something with “myContent”. In node.js, it'd be like this “open(path, funcName)”, and when the file content is read, your function “funcName” will be called and the file content is passed to your function as parameter. While Node is opening the file, it immediately runs other things, so it doesn't “block”. Example:

// example of non-blocking (async) reading file

datavar fs = require('fs');     // load file handling module

fs.readFile("/home/joe/xyz.txt", function (err, fileContent) {
    if (err) {throw err;} else {
        lineCount = fileContent.toString("utf8").match(/\n/g).length; // count lines
        console.log(lineCount);
    }
});

the fs.readFile method reads a file, and when it is ready, it calls the function you gave it. The point is that, it doesn't halt while it's trying to access the file. fs.readFile(filename, [options], callback)

Note: not everything in node.js is async. There are some functions that's synchronous, because it's just practical that way. For example, there is a sync version of file reading named fs.readFileSync. fs.readFileSync(filename, [options])

Simple HTTP Server

Here is a simple HTTP server.

// node.js simple http server

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('hi there\n');
}).listen(8000, '127.0.0.1');

console.log('Server running at http://127.0.0.1:8000/');

in the code, the require('http') loads a module named “http”, and returns a object that serves as a namespace.

http.createServer() return a web server object. http.createServer([requestListener])

When there is a request (event), the callback function is called.

The arguments passed to the callback function are request object and response object.

In the response object, you see “.writeHead()” method and “.end()” method.

response.writeHead()
Sends a response header to the request. response.writeHead(statusCode, [statusMessage], [headers])
response.end()
signal to server all response header and body are sent. response.end([data], [encoding])

here's a second version that streams out content after 2 seconds. (the point about this is that Node doesn't buffer, because that'd cause delay.)

// node.js simple http server

var http = require('http');

var s = http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});

    res.write("hi\n");

    setTimeout(function () {
        res.end("there\n");
    }, 2000)

});

s.listen(8000)

Start it by node filename.

In terminal, press Ctrl+z to suspend current “job”. Type fg to resume it. Press Ctrl+c to exit. [see Linux: Job Control]

To test a server, in terminal, you can use curl -i url to fetch page. The -i means show HTTP header in output too. If you have perl installed, you can also use GET url and HEAD url. [see Linux: wget (Download Web Page)]

Here is sample telnet session.

◆ curl -i localhost:8000
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Wed, 25 Dec 2013 21:42:43 GMT
Connection: keep-alive
Transfer-Encoding: chunked

hi
there

you can use apache benchmark tool, to test server performance. Like this ab -n 9 -c 9 http://localhost:8000/. The -n means number of request, the -c means number of current at a time. [see Testing Server Performance Using Apache Benchmark Tool]

Simple Chat Server (TCP/Socket Programing)

Here is a simple chat server, by creating a socket. [see TCP/IP Tutorial for Beginner]

// -*- coding: utf-8 -*-
// simple socket

var net = require('net');

var server = net.createServer(function (socket) {
    socket.write("hi\n");
    socket.end("you there\n");
});

server.listen(8000, '127.0.0.1');

This will create a simple server. When user connects, it'll just print “hi” and “there”, then disconnect. net

To test, in terminal type telnet localhost 8000. (to exit telnet, press Ctrl+], then type help.)

Here is a second version. This version, will echo back whatever user typed, and won't disconnect.

// -*- coding: utf-8 -*-
// simple echo chat server

var net = require('net');

var server = net.createServer(function (xx) {

    // xx is a parameter. It's Node's event object

    xx.write("hi\n");
    xx.write("you there\n");

    xx.on("data", function (dd) {
        xx.write(dd);
    });

});

server.listen(8000, '127.0.0.1');

Note: in the callback function, the argument passed to it is a event object. The generic event object has a set of methods, but specialized event usually has other methods. Events

◆ telnet localhost 8000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hi
you there
th
th
can you see me?
can you see me?
what
what
you
you

Here is a final version of chat server. Multiple people can connect to it, and see each other's typing.

// -*- coding: utf-8 -*-
// simple chat client

var net = require('net');

var socketList = [];

var server = net.createServer(function (xxsocket) {
    socketList.push(xxsocket);
    xxsocket.on("data", function (dd) {
        for (var i = 0; i < socketList.length; i++) {
            if ( socketList[i] == xxsocket ) {
                continue;
            }
            socketList[i].write(dd);
        }
    });

    xxsocket.on("end", function () {
        var i = socketList.indexOf(xxsocket);
        socketList.splice(i,1);
    });
});

server.listen(8000, '127.0.0.1');

Mashing Things Together: Run Different Things at Different Interval

This script run different things at different interval. It prints every 5 sec, and fetch a google.com page every 2 secs, and also run a webserver and spit out to connected client a string every 1 second.

// -*- coding: utf-8 -*-
// demo that Node can do multiple things, each with a different repeating interval

// print every 5 sec
setInterval(
    function () {console.log("world");}, 5000
)

console.log("hi");

var http = require('http');

// fetch Google every 2 sec
setInterval(
    function () {
        console.log("fetching google.com");
        http.get({"host": "google.com"},
                 function (res) {console.log(res.headers);})
    }, 2000
)

console.log("bbbb");

// serve web, print every 1 sec
var s = http.Server(function (req, res) {
    res.writeHead(200);
    setTimeout(function () {
        res.end("hello world\n");
    }, 1000);
});
s.listen(8000);

// hi
// { location: 'http://www.google.com/',
//   'content-type': 'text/html; charset=UTF-8',
//   date: 'Mon, 23 Dec 2013 10:13:24 GMT',
//   expires: 'Wed, 22 Jan 2014 10:13:24 GMT',
//   'cache-control': 'public, max-age=2592000',
//   server: 'gws',
//   'content-length': '219',
//   'x-xss-protection': '1; mode=block',
//   'x-frame-options': 'SAMEORIGIN',
//   'alternate-protocol': '80:quic' }
// hi
// fetching google.com

xah node.js tutorial (draft)

Node.js Tutorial

BUY ΣJS JavaScript in Depth