Node.js Code School course notes

Posted by Monik, 02 January 2015.
Programming Node.js
Course notes

These are the notes I took during the Node.js basic course from www.codeschool.com. It was a very good course. It guides through the basics of how to start with NodeJS.

Table of contents

Lesson 1

Minimal server

var http = require(‘http’);

http.createServer(function(request, response) {
   response.writeHead(200);
   response.write(“Hello, this is Bla”);
   response.end()
}).listen(8080);

Serving index.html

http.createServer(function(request, response) {
  response.writeHead(200);
  fs.readFile('index.html', function(error, contents){
    response.write(contents);
    response.end();
  });
}).listen(8080);

Lesson 2: Events

  • in Node.js objects can emit events
  • every such object is an instance of EventEmitter
  • the http.createServer is in fact taking the callback for 'request' event, we could as well write server.on('request', callback)
  • multiple handlers can be registered for same event

Custom EventEmitter

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

var chat = new EventEmitter();
chat.on('message', function(message){
  console.log(message);
});
chat.emit('message', 'blabla');

Lesson 3: Streams

Echoing the request to the user

response.writeHead(200);
request.pipe(response); // echo the request to the user

File upload

var file = fs.createWriteStream(‘file1.txt’);
request.pipe(file);
request.on(‘end’, function(){
  response.end(‘uploaded!’)
});

File upload with progress

var file = fs.createWriteStream('file1.txt');

var fileBytes = request.headers[content-length];
var uploadedBytes = 0;

request.on('readable', function(){
  var chunk = null;
  while(null !== (chunk = file.read())){
    uploadedBytes += chunk.length;
    var progress = (uploadedBytes/fileBytes)*100;
    response.write("Progress:"+ parseInt(progress,10)+"%\n");
  }

});

request.pipe(file);
request.on('end', function(){
  response.end('uploaded!')
});

Other useful things

  • file.pipe(process.stdout); - like console.log
  • reading in chunks:
    file.on('readable', function(){
      var chunk;
      while(null !== (chunk = file.read())){
        console.log(chunk.toString());
      }
    });
  • don't close writer stream once pipe is done:
    file.pipe(destFile, {end:false});

Lesson 4: Modules

my_module.js:
var foo = function(){...};
var bar = function(){...};
var baz = function(){...};
exports.foo = foo;
exports.bar = bar;

app.js:
var m = require("./my_module");
m.foo();
m.bar();

  • you can also do module.exports = foo, and then call directly foo(), but in this way you can export only one function
  • if you don't provide the "./" prefix for the module name, it will look in node_modules directory of the app, then the same directory in your home directory, if not then in /home, and if not then at the root path.
  • npm - Package Manager for Node - module repository, dependency management, easily publish your own modules, see npmjs.org
  • package.json - good practice to have this file in root of your app, with app info and required dependency versions; then, when you run "npm install", these dependencies will be installed if not there yet;
  • package.json is also present in module root folder, as one module may depend on another one
  • semantic versioning: x.x.x, you can also specify ~1.8 to get the latest 1.8.x version; see www.semver.org

Lesson 5: Express

Basic example

require('express');

var app = express();
app.get('/', function(request, response){
  response.sendFile(__dirname + "/index.html");
});
app.listen(8080);

Request with dynamic URI param

app.get('/tweets/:username', function(request, response){
  var username = request.params.username;
  options = {
    protocol: "http:",
    host: "api.twitter.com",
    pathname: "/1/statuses/user_timeline.json",
    query: {screen_name: username, count: 10}
  };
  var twitterUrl = url.format(options);
  request(twitterUrl).pipe(response);
});
app.listen(8080);

Templates - Embedded Java Script

  • npm install --save ejs
  • the templates are in "views" directory of your app by default
  • to put the data in the template, use a callback function in request function:
    request(twitterUrl).pipe(response);
    request(twitterUrl, function(err,res,body){
      var tweets = JSON.parse(body);
      //that's the data that will end up in the template:
      response.locals = {tweets:tweets, name:username};
      response.render('tweets.ejs');
    });

    tweets.ejs:
    <h1>Tweets for <%= name %></h1>
    <ul>
      <% tweets.forEach(function(tweet){
         <li><%= tweet.text %></li>
      <%});%>
    </ul>

Lesson 6: Sockets

Server side

app.js
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(client){
  console.log("New client connected..");
  //when client sends a message, emit it to all other clients
  client.on('messages', function(data){
    client.broadcast.emit('question',data);
  });
  //or just emit one dummy message to the client
  client.emit('messages',{foo:"bar"});
});
server.listen(8080);

Client side

index.html:
<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost:8080');
  //the client can receive messages like this


  server.on('messages', function(data){

    console.log(data.foo);

  });


</script>

Lesson 7: Persisting Data

  • still the chatroom example: if someone joins later, they don't see the previous messages; so we store them in server in memory - but if server restarts, then it's bad
  • so we can use a DB - Node.js has drivers for most DBses which are NON Blocking!
  • example: Redis (key value store), very good docu: npm install --save redis:
    I'm skipping that part, it's redis specific


Comments


Comments: