Node.js Video Tutorial by Ryan Dahl, with Annotation

, , …,
Want to master JavaScript in a month? Commit. Buy Xah JavaScript Tutorial. You also get Xah HTML Tutorial and Xah CSS Tutorial.

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.

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

〈Introduction to Node.js with Ryan Dahl〉

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. 〔☛ Xah JavaScript Tutorial

here's 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

The functions 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)

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 ƒ as the last parameter, and this function ƒ will be called when it is ready. The function ƒ passed as argument and later invoked, 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/jane/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's a sync version of file reading named fs.readFileSync. ⬢ fs.readFileSync(filename, [options])

Simple HTTP Server

Here's 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.

The http.createServer() returns a web server object. ⬢ http.createServer([requestListener])

When there's 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.

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. 〔☛ Linux: Job Control Tutorial

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. 〔☛ Linux: wget & curl Tutorial

Here's 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. 〔☛ Testing Server Performance Using Apache Benchmark Tool

Simple Chat Server (TCP/Socket Programing)

Here's a simple chat server, by creating a socket. 〔☛ Computer Networking, TCP/IP Basics

// -*- 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's 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's 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
blog comments powered by Disqus