044 Node

26 May 2013

NodeJS is a V8 engine based event-driven I/O platform to build applications. In this episode we will explore the concepts of asynchronous, non-blocking programs along with how to schedule or delay the execution of a function with event loops and child processes. Lastly, we will end off with a simple TCP chat server.

Download video: mp4

Sample code: Github

Version: v0.10.8

Similar episodes: 009 Package Managers

##Background on Node

  1. Main website, documentation and twitter
  2. Original NodeJS presentation and an intro to node.js with Ryan Dahl

##Things to learn with Node

###1. install and run

  1. install nodejs, npm (package manager) and nvm (manage node versions)

    ``` $ npm –version 1.2.21

    $ node –version v0.10.7

    $ nvm ls v0.8.18 v0.10.4 v0.10.7 current: v0.10.7 default -> 0.10.7 (-> v0.10.7) ```

  2. run the node REPL in the command line with just node to type in javascript! to quit the REPL, it’s cntrl + c. Also, try to query the global variable process including process.env, etc

    $ node > console.log('hello world in node!!'); hello world in node!! undefined > typeof({}); 'object' > process

  3. run javascript code with node in file hello.js (not in browser!)

    console.log('hello world in node!!');

    run in command line:

    $ node hello.js hello world in node!!

###2. understanding async in javascript

  1. with Ruby in file index.rb

    ``` require ‘timeout’

    puts ‘Before - ‘ + Time.new.inspect sleep(5) puts ‘After - ‘ + Time.new.inspect ```

    run the file in command line with ruby index.rb. notice the 2 seconds time stamp difference

    Before - 2013-05-24 12:40:17 +0800 After - 2013-05-24 12:40:22 +0800

  2. with Python in file index.py

    ``` from datetime import datetime import time

    print ‘Before - ‘ + datetime.now().strftime(“%Y-%m-%d %H:%M:%S”) time.sleep(5) print ‘After - ‘ + datetime.now().strftime(“%Y-%m-%d %H:%M:%S”) ```

    run the file in command line with python index.py. notice the 2 seconds time stamp difference

    Before - 2013-05-24 12:43:23 After - 2013-05-24 12:43:28

  3. with C in file index.c

    ``` #include #include #include

    int main(void) {

    time_t rawtime; struct tm * timeinfo;

    time ( &rawtime ); timeinfo = localtime ( &rawtime ); printf(“Before - %s\n”, asctime (timeinfo) );

    usleep(5000000);

    time ( &rawtime ); timeinfo = localtime ( &rawtime ); printf(“After - %s\n”, asctime (timeinfo) );

    }

    ```

    run the file in command line with clang index.c && a.out. notice the 2 seconds time stamp difference

    Before - Fri May 24 12:45:18 2013 After - Fri May 24 12:45:23 2013

  4. with node in file index.js with continuation passing style where a function invokes a callback after the operation setTimeout is complete

Event I/O programming in other languages:

###3. modules

using CommonJS modular patterns

my own modules

core modules - create an http server with the http module

``` var http = require(‘http’);

var server = http.createServer(function(req, res) { res.writeHead(200, {‘Content-Type’: ‘text/plain’}); res.write(‘Hello World!’); res.end(); });

server.listen(4000);

console.log(‘Server running at localhost:4000’); ```

forgo the variable declarations and other shortcuts:

``` require(‘http’).createServer(function(req, res) { res.writeHead(200, {‘Content-Type’: ‘text/plain’}); res.end(‘Hello World!’); // try: res.end(req.url); }).listen(4000);

console.log(‘Server running at localhost:4000’); ```

test it out!

external module: 3rd party modules like connect in file server.js. Install the connect module in the command line with $ npm install connect

``` var connect = require(‘connect’);

connect.createServer(function(req, res) { res.end(‘Hello World in NodeJS!’); }).listen(8080); ```

  1. try with embedded html tags:

    ``` … res.end(‘<h1>Hello World in NodeJS!’); …

    ```

  2. try with files public/index.html and public/css/style.css in the file server.js

    ``` var connect = require(“connect”);

    connect(connect.static(__dirname + “/public”)).listen(8000); ```

###4. event driven programming

  1. explore 4 types of scheduling events:

    ``` var repeat = setInterval(function() { console.log(‘Repeat!’); }, 2000);

    var timeout = setTimeout(function() { console.log(“Timeout in 4s”); }, 4000);

    clearTimeout(repeat); // try with: clearTimeout(timeout);

    console.log(‘Hello :)’); ```

  2. explore event loops with process.nextTick. Which gets execute first and why?

    1. plain console.log

      console.log('Before'); console.log('After');

    2. with an infinite loop in between

      ``` console.log(‘Before’);

      var a = 0; while(true) { a ++; }

      console.log(‘After’); ```

    3. with a task that will execute immediately after the main program

      ``` console.log(‘Before’);

      process.nextTick(function() { console.log(“tick”); });

      console.log(‘After’); ```

    4. with 2 functions to execute after the main program

      ``` console.log(‘Before’);

      process.nextTick(function() { console.log(“tick 1”); });

      console.log(‘After’);

      process.nextTick(function() { console.log(“tick 2”); });

      ```

      replace with an infinite loop…

      ``` console.log(‘Before’);

      process.nextTick(function() { console.log(“tick 1”); });

      console.log(‘After’);

      process.nextTick(function() { console.log(“tick 2”); });

      ```

      use delayed functions…

      ``` console.log(‘Before: ‘ + new Date().getSeconds());

      setTimeout(function() { console.log(‘Timeout in 2s: ‘+ new Date().getSeconds()); }, 2000);

      process.nextTick(function() { console.log(‘tick 2 ‘ + new Date().getSeconds()); setTimeout(function() { console.log(‘Timeout in 2s in next tick ‘+ new Date().getSeconds()); }, 2000); });

      ```

  3. child process

    1. execute a command line process

      var exec = require('child_process').exec; console.log('Before'); exec('ls -al', function(err, stdout, stderr) { if (err) { console.log('child process exited with error code', err.code); return; } console.log(stdout); }); console.log('After');

    2. execute another file from parent.js

      ``` var exec = require(‘child_process’).exec;

      console.log(‘Before: ‘ + new Date().getSeconds() );

      exec(‘node child.js’, function(err, stdout, stderr) { console.log(‘stdout:\n’, stdout); });

      console.log(‘After: ‘ + new Date().getSeconds() );

      ```

      calling the file child.js

      setTimeout(function() { console.log("Timeout in 1s: " + new Date().getSeconds() ); }, 1000);

###5. networking - a simple tcp chat

a simple tcp chat server based on Ryan Dahl’s TCP Chat server

var server = require('net').createServer(),
  sockets = [];

server.on('connection', function(socket) {

  console.log('got a new connection');
  sockets.push(socket);

  socket.on('data', function(data) {
    console.log('got data:', data);
    sockets.forEach(function(otherSocket) {

      if (otherSocket !== socket) { // prevents echo
        otherSocket.write(data);
      }
    });
  });

  socket.on('close', function() {
    console.log('connection closed');
    var index = sockets.indexOf(socket);
    sockets.splice(index, 1);
  });

});

server.on('error', function(err) {
  console.log('Server error:', err.message);
});

server.on('close', function() {
  console.log('Server closed');
});

server.listen(4001);

start the chat server in the command line with node chat.js

open a few connections in command line tabs with nc localhost 4001

##More Resources on Node

  1. Node Beginner book
  2. Professional Node and Node Tuts by Pedro
  3. Node Guide by Felix
  4. ExpressJS web application framework for Node

##Build Link of this episode

Tech.pro for many web development tutorials