This article is part of the article series "Node.JS Modules You Should Know About."
<- previous article next article ->

node logoHello everyone! This is the eighth post in my new node.js modules you should know about article series.

The first post was about dnode - the freestyle rpc library for node, the second was about optimist - the lightweight options parser for node, the third was about lazy - lazy lists for node, the fourth was about request - the swiss army knife of HTTP streaming, the fifth was about hashish - hash combinators library, the sixth was about read - easy reading from stdin, the seventh was about ntwitter - twitter api for node.

This time I'll introduce you to socket.io. I bet that most all of you already know socket.io, however I had several people message me to do an article on socket.io, so here it is.

Socket.io makes websockets and realtime possible in all browsers. It also enhances websockets by providing built-in multiplexing, horizontal scalability, and automatic JSON encoding/decoding. Socket.io is written by Guillermo Rauch, who's the co-founder of LearnBoost.

Socket.io always chooses the best realtime communication method possible. Here is the list of all the communication methods it supports:

  • WebSocket
  • Adobe┬« Flash┬« Socket
  • AJAX long polling
  • AJAX multipart streaming
  • Forever Iframe
  • JSONP Polling

For example, if you're using Chrome, then socket.io will use websockets. If your browser doesn't support websockets, it will try to use flash sockets, then it will try long polling, etc.

Now let's look at a very basic socket.io example:

var io = require('socket.io');
var express = require('express');

var app = express.createServer()
var io = io.listen(app);

app.listen(80);

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
  socket.on('disconnect', function () {
    console.log('user disconnected');
  });
});

This example uses the awesome express node web framework (I'll blog about it soon) to setup a web server on port 80, and attaches socket.io to it.

Socket.io then listens for new connections and when a new connection from the browser is created, it emits news event that sends the { hello: 'world' } hash back to the browser.

It also setups a listener for my other event and it listens for disconnects. When the web application emits this event, socket.io calls the function (data) { console.log(data); } callback, that just prints the data to console. When the client disconnects, it logs this event to console also.

Here is the client side (in the web browser):

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

First we include the socket.io.js script, and then we create a socket.io connection to http://localhost. Here socket.io chooses the best communication method that the browser supports. If it's Chrome then it will be websockets, then if you have flash, then it will try flash sockets, then long polling, then multipart streaming, then forever iframe method, and finally jsonp polling. Then we listen on news event and when we receive it, we emit my other event.

This way you can build all kinds of awesome realtime applications, such as web chat servers and web irc clients.

There are many other features that socket.io supports, such as namespaces, volatile messages, message confirmations and message broadcasting. See the documentation to learn all about this awesomeness!

You can install socket.io through npm as always:

npm install socket.io

Socket.io on GitHub: https://github.com/LearnBoost/socket.io.

Also take a look at dnode that allows to call functions over socket.io!

Sponsor this blog series!

Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! Email me and we'll set it up!

Enjoy!

If you love these articles, subscribe to my blog for more, follow me on Twitter to find about my adventures, and watch me produce code on GitHub!

This article is part of the article series "Node.JS Modules You Should Know About."
<- previous article next article ->

node logoHello everyone! This is the seventh post in my new node.js modules you should know about article series.

The first post was about dnode - the freestyle rpc library for node, the second was about optimist - the lightweight options parser for node, the third was about lazy - lazy lists for node, the fourth was about request - the swiss army knife of HTTP streaming, the fifth was about hashish - hash combinators library, the sixth was about read - easy reading from stdin.

This time I'll introduce you to ntwitter - asynchronous Twitter REST, streaming and searching client API. This module is maintained by Charlie McConnell, aka AvianFlu. Ntwitter was actually created by technoweenie, but since then maintainers have changed several times.

To use it, you'll need to get the API keys. That can easily be done at dev.twitter.com. Just register a new App, and you'll get the keys.

Here is an example ntwitter app that tweets:

var twitter = require('ntwitter');

var twit = new twitter({
  consumer_key: 'Twitter',
  consumer_secret: 'API',
  access_token_key: 'keys',
  access_token_secret: 'go here'
});

twit
  .verifyCredentials(function (err, data) {
    if (err) {
      console.log("Error verifying credentials: " + err);
      process.exit(1);
    }
  })
  .updateStatus('Test tweet from ntwitter/' + twitter.VERSION,
    function (err, data) {
      if (err) console.log('Tweeting failed: ' + err);
      else console.log('Success!')
    }
  );

Here is how to search through ntwitter API:

var twitter = require('ntwitter');

var twit = new twitter({
  consumer_key: 'Twitter',
  consumer_secret: 'API',
  access_token_key: 'keys',
  access_token_secret: 'go here'
});

twit.search('nodejs OR #node', function(err, data) {
  if (err) {
    console.log('Twitter search failed!');
  }
  else {
    console.log('Search results:');
    console.dir(data);
  }
});

You can also use Twitter's streaming API:

var twitter = require('ntwitter');

var twit = new twitter({
  consumer_key: 'Twitter',
  consumer_secret: 'API',
  access_token_key: 'keys',
  access_token_secret: 'go here'
});

twit.stream('statuses/sample', function(stream) {
  stream.on('data', function (data) {
    console.log(data);
  });
});

Here is a list of all the possible statuses/* that you can stream from.

Note how you don't need to login into twitter to do searching and streaming.

You can stream someone's tweets this way:

var twitter = require('ntwitter');

var twit = new twitter({
  consumer_key: 'Twitter',
  consumer_secret: 'API',
  access_token_key: 'keys',
  access_token_secret: 'go here'
});

twit.stream('user', {track:'nodejs'}, function(stream) {
  stream.on('data', function (data) {
    console.dir(data);
  });
  stream.on('end', function (response) {
    // Handle a disconnection
  });
  stream.on('destroy', function (response) {
    // Handle a 'silent' disconnection from Twitter, no end/error event fired
  });
});

Finally, you can stream tweets from certain locations, defined by bounding boxes:

var twitter = require('ntwitter');

var twit = new twitter({
  consumer_key: 'Twitter',
  consumer_secret: 'API',
  access_token_key: 'keys',
  access_token_secret: 'go here'
});

twit.stream('statuses/filter', {'locations':'-122.75,36.8,-121.75,37.8,-74,40,-73,41'},
function(stream) {
  stream.on('data', function (data) {
    console.log(data);
  });
});

You can use Cole Gillespie's node-finden module to get the geographical coordinates for bounding boxes. Here is how Cole's software looks:

That's it. Super easy way to do all things twitter with ntwitter.

You can install ntwitter through npm as always:

npm install ntwitter

Ntwitter on GitHub: https://github.com/AvianFlu/ntwitter.

Sponsor this blog series!

Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! Email me and we'll set it up!

Enjoy!

If you love these articles, subscribe to my blog for more, follow me on Twitter to find about my adventures, and watch me produce code on GitHub!

This article is part of the article series "Node.JS Modules You Should Know About."
<- previous article next article ->

node logoHello everyone! This is the sixth post in my new node.js modules you should know about article series.

The first post was about dnode - the freestyle rpc library for node, the second was about optimist - the lightweight options parser for node, the third was about lazy - lazy lists for node, the fourth was about request - the swiss army knife of HTTP streaming, the fifth was about hashish - hash combinators library.

This time I'll introduce you to a brand new module called read. Read was created just yesterday by Isaac Z. Schlueter, the author of npm. Read is basically read(1) for node. You can read input from stdin with it easily.

Here is an example,

var read = require('read');

read({ prompt : 'Username: ' }, function (err, user) {
  read({ prompt : 'Password: ', silent : true }, function (err, pass) {
    console.log(user, pass);
    process.stdin.destroy();
  });
})

Nesting functions like this is ugly, so you better use seq, the asynchronous flow combinators library, by James Halliday. (I'll introduce you to this module some time soon.) Here is how it looks with seq:

var read = require('read');
var Seq = require('seq');

Seq()
  .seq(function () {
    read({ prompt : 'Username: ' }, this.into('user'));
  })
  .seq(function () {
    read({ prompt : 'Password: ', silent : true }, this.into('pass'));
  })
  .seq(function (pass) {
    console.log(this.vars.user, this.vars.pass);
  });

Here are all the options read supports:

prompt  - What to write to stdout before reading input.
silent  - Don't echo the output as the user types it.
num     - Max number of chars to read from terminal.
delim   - The char that means we're done. Default: "\n"
timeout - Number of ms to wait for user input before giving up.

Note: If silent is true, or num is set, or delim is something other than "\n", then read will set raw mode, and read character by character.

You can install read through npm as always:

npm install read

Sponsor this blog series!

Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! Email me and we'll set it up!

Enjoy!

If you love these articles, subscribe to my blog for more, follow me on Twitter to find about my adventures, and watch me produce code on GitHub!

This article is part of the article series "Node.JS Modules You Should Know About."
<- previous article next article ->

node logoHello everyone! This is the fifth post in my new node.js modules you should know about article series.

The first post was about dnode - the freestyle rpc library for node, the second was about optimist - the lightweight options parser for node, the third was about lazy - lazy lists for node, the fourth was about request - the swiss army knife of HTTP streaming.

This time I'll introduce you to hashish. Hashish is written by James Halliday, who's my co-founder of Browserling and Testling. In case you're wondering why I am blogging about so many of his modules, it's because he's written 88 of them and each one of them is absolutely brilliant.

Hashish is a JavaScript hash combinator library, or in other words, it contains a bunch of hash data structure manipulation functions.

Check out this example,

var Hash = require('hashish');

Hash({ a : 1, b : 2, c : 3, d : 4 })
    .map(function (x) { return x * 10 })
    .filter(function (x) { return x < 30 })
    .forEach(function (x, key) {
        console.log(key + ' => ' + x);
    })
;

Here a Hash object is constructed from the hash { a : 1, b : 2, c : 3, d : 4 }. Next, a function that multiplies each hash value by 10 is mapped over. At this moment the hash has become { a : 10, b : 20, c : 30, d : 40 } Then a filter is applied that filters only hash elements that have value less than 30. At this point hash is { a : 10, b : 20 }. Finally forEach combinator is applied all the elements that are left and the key, value pair is printed, producing the following output:

a => 10
b => 20

Notice how similar the interface for hash manipulation is to the node-lazy that I wrote about a few days ago. All the combinators can be chained so your code stays beautiful.

If you can't or don't want to chain the functions, hashish also allows each function in the chainable interface to be attached to Hash in chainless form:

var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };

var mapped = Hash.map(obj, function (x) {
    return x * 10
});

console.dir(mapped);

Notice how this code calls Hash.map on obj hash. The output is each hash value multiplied by 10:

{ a: 10, b: 20, c: 30, d: 40 }

Hashish also provides various attributes in the chaining interface and functions in the Hash.xxx interface. For example:

$ node
> var Hash = require('hashish');
> var obj = { a : 1, b : 2, c : 3, d : 4 };
>
> Hash(obj).keys
[ 'a', 'b', 'c', 'd' ]
> Hash(obj).values
[ 1, 2, 3, 4 ]
> Hash(obj).length
4

You can install hashish through npm:

npm install hashish

Sponsor this blog series!

Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! Email me and we'll set it up!

Enjoy!

If you love these articles, subscribe to my blog for more, follow me on Twitter to find about my adventures, and watch me produce code on GitHub!

This article is part of the article series "Node.JS Modules You Should Know About."
<- previous article next article ->

node logoHey everyone! This is the fourth post in my new node.js modules you should know about article series.

The first post was about dnode - the freestyle rpc library for node, the second was about optimist - the lightweight options parser for node, the third was about lazy - lazy lists for node.

This time I'll introduce you to a very awesome module called request by Mikeal Rogers. Request is the swiss army knife of HTTP streaming.

Check this out:

var fs = require('fs')
var request = require('request');

request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))

Pow! You just streamed the response of HTTP request to http://google.com/doodle.png into doodle.png local file!

Here is more awesome stuff:

var fs = require('fs')
var request = require('request');

fs.readStream('file.json').pipe(request.put('http://mysite.com/obj.json'))

Pow! It streamed your local file file.json to http://mysite.com/obj.json as HTTP PUT request!

var request = require('request');

request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))

Pow! This just streamed a HTTP GET from http://google.com/img.png to HTTP PUT to http://mysite.com/img.png.

At Browserling we use this module for streaming data to and from couchdb. Here is an example that saves a JSON document at mikeal's test couchdb:

var request = require('request')
var rand = Math.floor(Math.random()*100000000).toString()

request({
  method: 'PUT',
  uri: 'http://mikeal.iriscouch.com/testjs/' + rand,
  multipart: [
    {
      'content-type': 'application/json',
      'body': JSON.stringify({
        foo: 'bar',
        _attachments: {
          'message.txt': {
            follows: true,
            length: 18,
            'content_type': 'text/plain'
           }
         }
       })
    },
    { body: 'I am an attachment' }
  ] 
}, function (error, response, body) {
  if(response.statusCode == 201){
    console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand);
  } else {
    console.log('error: '+ response.statusCode);
    console.log(body);
  }
})

Install it via npm, as always:

npm install request

Sponsor this blog series!

Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! Email me and we'll set it up!

See ya!

If you love these articles, subscribe to my blog for more, follow me on Twitter to find about my adventures, and watch me produce code on GitHub!