Deliver real-time information to your users using node.js

July 26th 2010

You must have already heard about node.js, if not, it’s an evented input/output server based on Google V8 engine. That means that as soon as the server receives information it can respond and send relevant information back to your front-end. You can then treat this information the way you want. What is so cool about it is that if you know javascript you can code a node.js server and it really is a lot of fun!

In this article, I’ll cover the basics to be able to build a simple server that will respond to an “admin” user input and then broadcast a message to all users connected on the website. Based on that, you’re then free to apply it to whatever needs you may have.

Please note that some basic server knowledge is required, like installing software with command line and forward requests to specific ports.

The demo

First open the live feed demo page, then open the live feed admin page. Try to resize them so you can see both, then click on the display buttons on the admin page, watch the magic happen on the live feed page!

The basics

How does that real-time thing work? Well it’s actually quite simple. Every time a user connects to my demo page, I open an ajax connection, that ajax connection wait for the server to send data. Once it receives data, it’s processed, the connection is closed and a new one is opened. This can be called Comet, long polling, ajax push, HTTP Streaming and a bunch of other names. You can also do long-polling in PHP but since node.js is a dedicated server it does a better job at handling the load.

The setup

If you’ve never installed node.js on your server, you first need to do it. The documentation is here. Make sure you have g++ installed on your server. Simply run: “sudo apt-get install g++” if you’re on Ubuntu, it’ll either tell you it’s up to date or install it.

Here’s how I proceeded to install node.js, 4 easy steps:

[/sources] > git clone git://github.com/ry/node.git
[/sources] > cd node
[/sources/node] > ./configure
...wait...
[/sources/node] > make
...wait...
[/sources/node] > sudo make install
...wait...
'install' finished successfully (0.193s)
DONE

So you should now be setup with node.js on your server, let the fun begin.

The server (link to the source)

This demo uses two main javascript file, one for the server and one for the client. Let’s begin by tearing down the server javascript file.

The first thing you need to do is load the modules required for your app, in this case we need the http, sys, url and querystring module.

var http = require("http"),
    sys = require("sys"),
    url = require("url"),
    qs = require("querystring");

I then declared my global variables for this applications, they are as follow:

var ITEMS_BACKLOG = 20;

var urlMap = {
  '/real_time_feed' : function (req, res) {
    var since = parseInt(qs.parse(url.parse(req.url).query).since, 10);
    feed.query(since, function (data) {
      res.simpleJSON(200, data);
    });
  },
  '/send_feed_item' : function (req, res, json) {
    feed.appendMessage( json );
    res.simpleJSON(200, {});
  }
}

The ITEMS_BACKLOG is the max number of items the server keeps in memory, this way you can make sur it never runs out of memory, you’ll see where it’s being used later.

I then declare my urlMap, these are the URLs the server listens to and the code to execute upon calling. It’s fairly straight forward, there’s one very important thing you need to know tho, it’s that since node.js runs on a different port than your normal webserver (a webserver usually runs on port 80), you need to forward the calls on those URLs to your node.js server port.

In my case, I use NGINX as my webserver and node.js runs on port 8001. Here’s what my NGINX configuration file looks like:

# Send request to node.js on port 8001
location ~* ^(/real_time_feed|/send_feed_item)$
{
  proxy_pass http://localhost:8001;
}

You see that I redirect both URLs in my “urlMap” to the node.js server port. Might not be the most efficient way but since you cannot do cross-domain posting in ajax, it’s the only solution I found for now.

Then comes the meat, the server itself, it’s fairly easy to create, you just need to invoke the “createServer” method and make it listen to a specific port.

http.createServer(function (req, res) {
...
}).listen(8001);

All requests and responses will be processed in here, so you need some code in there right? Here it is:

http.createServer(function (req, res) {
  // Get the url and associate the function to the handler
  // or
  // Trigger the 404
  handler  = urlMap[url.parse(req.url).pathname] || notFound;

  var json = "";

  if(req.method === "POST"){
    // We need to process the post but we need to wait until the request's body is available to get the field/value pairs.
    req.body = '';

    req.addListener('data', function (chunk) {
      // Build the body from the chunks sent in the post.
        req.body = req.body + chunk;
      })
      .addListener('end', function () {
        json = JSON.stringify(qs.parse(req.body));
          handler(req, res, json);
      });
  }else{
    handler(req, res);
  }

  res.simpleJSON = function (code, obj) {
    var body = JSON.stringify(obj);
    res.writeHead(code, {
      "Content-Type": "text/json",
      "Content-Length": body.length
    });
    res.end(body);
  };

}).listen(8001);

So the first thing I do is go get the function that need to be invoked in my urlMap and assign it to my handler. Then depending on the type of request, I either get the posted data and send a response or just straight invoke the handler of the URL called and send a response.

Now you’ll see that in my urlMap I call the feed object, this object has 2 methods, one for querying and one for appending content to the feed.

The “query” method, don’t respond until there’s valid content to send, that’s why the ajax call keeps running, it’s just there waiting. The “appendMessage” method…well she append content to my “real_time_items” array.

// Handles the feed push and querying.
var feed = new function () {
  var real_time_items = [],
      callbacks = [];

  this.appendMessage = function (json) {
    // Append the new item.
    real_time_items.push( json );

    // Log it to the console
    sys.puts(new Date() + ": " + JSON.parse(json).type + " pushed");

    // As soon as something is pushed, call the query callback
    while (callbacks.length > 0)
      callbacks.shift().callback([JSON.parse(json)]);

    // Make sur we don't flood the server
    while (real_time_items.length > ITEMS_BACKLOG)
      real_time_items.shift();
  };

  this.query = function (since, callback) {
    var matching = [];

    for (var i = 0; i < real_time_items.length; i++) {
          var real_time_item = real_time_items[i];
          if (real_time_item.timestamp > since)
            matching.push(real_time_item)
    }

    if (matching.length != 0) {
      callback(matching);
    } else {
      callbacks.push({ timestamp: new Date(), callback: callback });
    }
  };
};

That’s basically it for the server!

The client (link to the source)

What you need to do on the client side is very simple, you only need to start an ajax call that restarts when it receive a response:

function longPoll_feed () {
  //make another request
  $.ajax({
    cache: false,
    dataType: 'json',
    type: "GET",
    url: "/real_time_feed",
    error: function () {
      //don't flood the servers on error, wait 10 seconds before retrying
      setTimeout(longPoll_feed, 10*1000);
    },
    success: function (json) {
      display_event(json);

      //if everything went well, begin another request immediately
      //the server will take a long time to respond
      //how long? well, it will wait until there is another message
      //and then it will return it to us and close the connection.
      //since the connection is closed when we get data, we longPoll again
      longPoll_feed();
    }
});
}

So that ajax call listens to what is sent on the “real_time_feed” url. Once it receives data, it processes them.

Since it’s JSON that is returned to my views, I can then treat it the way I want. This file need to be included in the HTML file that will receive the live content.

The big merge

Ok so now you have your server javascript file and your client javascript file. The first thing you need to do is create an HTML page in which you’ll include the client.js file, I my case, it’s the index.html file.

Now for the server.js file, you actually need to connect via command line and start the node.js server like so:

[scaron] > node /path/to/server.js
Server running at http://127.0.0.1:8001/

And finally, to be able to send content to the server in real time, you need to POST content to the url “/send_feed_item”. If you remember in my URL map, I have setup this url to append content to my feed. So a simple ajax post should do the trick to post content, that’s what I do in my admin page.

$.post(
  'http://nodejs.no-margin-for-errors.com/send_feed_item',
   json,
  function(){
     // Done!
  }
);

The sources

All the sources are available on github, feel free to fork them and play with it yourself.

The possibilities

Let’s just say you watch a live conference on ustream.tv and the speaker mention some website, with node.js he could be able to send you to this website in real time as long as you are connected to his server or you could be watching live news on a website and they mention traffic, you could then be presented a Google traffic map live as they talk about it on the stream.

The possibilites are endless, this post covers only the basics, I’ll let your mind do the rest 😉

141 Responses to “Deliver real-time information to your users using node.js”


  1. は当然 | インターネットサイト私はあなたのインターネットウェブ好きですが、取るために、あなたが持っている非常に綴りで| 現れ見える いくつかの自分の投稿の。 発見 困難トラブル問題と私はそれらのいくつかはスペルでいっぱいであること本当にを通知するために煩わしいです。 再びそれにもかかわらず、私はきっと来ます!

  2. 私はあなたがしたの努力のためにあなたに感謝したいと思います。また、将来の |ハイグレードブログウェあなたからのポスト|私は全く同じ同じ願っています。 実際に ウェブサイト今行くあなたの創作能力が自分のスクリーンドアの瞬間を得るために私にインスピレーションを与えてきました。 実際に 迅速ブログはその翼を広げており、成長しています。あなたの書き込みアップは素晴らしいです例。ちょっと

  3. * それにもかかわらず妹になります探し|私は{探していたまさにhollywood`

  4. 例外 サイト。ここで情報 がたくさん。 仲間も美味しいで共有ANS に送る| 私は私は。そして当然、あなたの汗をありがとう!

  5. 。私は単にあなたのブログにつまずいたと私は本当にあなたのブログの記事を閲覧愛していると言うことを望みました。すべての後、私はあなたがもう一度すぐに書き込みを望んフィードとイムに加入することになります!

  6. 私は本当にあなたのサイトで起こって持っているこのテンプレートをお楽しみください。ところでデザインの名前は何ですか?私は私のクラスのプロジェクトのために作成するつもりですWebページのこのスタイルを使用して考えました。

  7. 私の妹は私のために、このインターネットサイトをブックマークして、私は過去数時間のためにそれを通過してきました。これは本当に私たちのクラスのプロジェクトのために私と私のクラスメートを助けるために起こっています。ところで、私はあなたが書いた方法のように。

  8. ? 私はあなたに出会ったことを| 嬉しく幸せ私は正確に何youreの言うとイムを聞きます。あなた純粋 youreのが話して知っている、あなたはなさ私はのように私は感じてはるか| | もっと学ぶあるべきロット詳細はるか。このいただきありがとうございます。イム正式に巨大なあなたのブログのファン

  9. は私が持っている 閲覧てオンライン 以上 3時間後半のような 、しかし I 決して 見つかりませんでした 魅力あなたのような記事。私のために| 十分な十分な 価格の価値 | それはそれはです。 私の意見で、もしすべてのウェブマスターやブロガー作ら優れた |のようなコンテンツコンテンツ素材 おそらくあなたをやった、インターネット でなければならない もっとたくさん 便利な役立ちます。 あなたがした 導入 {| すべてのすべて

  10. ああ、それはあなたかのように思われる親愛なるサイト発言それは |は信じて私たちは私の初期消費投稿ステッチゴーイング·ホーム私が提出した状態項目、私は問題 実際あなたウェブサイトを楽しんで。私は適切 |作家が、私は今それにもかかわらず 野心的なウェブログ午前事| に向けての新人。 提案と未経験のブロガーに関するヒントあなたは、任意の種類を持っています!私本当に純粋それを楽しむ…またあなたがチュニジア信じられないほどの発表を聞いた…よろしくフラッシュウェブサイトビルダー

  11. サイト上でいい仕事を続けます。大好きです。いくつかのより多くの頻繁な更新を使用していますが、笑、あなたが行うには良いものを持っていることをかなり確信してイムでした。 =)

  12. を読んでたくさんの楽しみを持っていた私はあなたがここに正しく行わ受けいたしますできるだけ多くを愛しました。スケッチは、あなたのオーサリング材料は、スタイリッシュな、魅力的です。それにもかかわらず、あなたは以下を提供することを望むことが焦りを乗り越えgetコマンド。体調不良は、紛れもなく、ほぼ頻繁に内部の場合、あなたがこの増加を遮蔽まったく同じため、再びより以前来ます。

  13. 適切な意思決定をするために信頼する厳しいものになることができます。それは信頼を構築するために年かかります。あなたは私が何を意味するか知っていればそれは本当に偶然doesntの。

  14. その巨大なポスト。私は、誰もが何度も何度もそれを訪問したいと確信しています。この記事を読んだ後、私は実際には、誰のために非常に有用であるいくつかの非常にユニークな情報を得ました。これは、いくつかの重要な情報を経験しての投稿です。私は将来的に、このような転記が上に行くべきであることを願っています。

  15. 非常に興味深い ポイント我慢|ありがとう| |に関しては、| 投稿するためにそれを感謝おかげで、述べました。 。 ‘無知、ルートおよびすべての悪の茎。」プラトンによって

  16. 。私が意味する、私はそれを読むために私のオプションだったけど、私は本当にヤウドが言うに注目度抜群の何かを持っていると思いました。私が聞くすべては、あなたがあまりにも忙しいしゃべれなかっするべきであるべきであるおそらく修復することができます| あなたがいることを何かについて泣き言の束さ注目を探しに。

  17. こんにちはバディ。私は、ほとんどのに純粋にのみ、このような記事だけでなく、Webページのすべてのものを愛し、私!その記事は真実で大丈夫わかりやすく簡単に理解書かれており、同様に理想的です。ワンズワードプレスのテーマは、同様に印象的です!明らかに、私はその可能ダウンロードでなければならないところを見つけ出すために素晴らしいことでしょう。いい仕事を維持する方法は、特定のこと。あなたが最も、インターネット上のあなたとロットより少ない数のスパマーとして、ウェブ上のすべての所有者であってもより多くのこれらのタイプを必要としています。素晴らしい仲間。それは多くの場合、あなたがこのような記事に出くわすことはありません

  18. [url=http://www.gginza.com/%E3%82%A2%E3%83%90%E3%82%A6%E3%83%88/item_2.html]父親になる男より感性。職場でもビジネスが忙しくて、心の中は常に牽掛――も子どもに与えたい多くの愛と付き添って、子どもの成長を楽しむ喜び。シチズン純黒版スーパー空の鷹JY8009-55E腕時計、身の人の親のエリートの事を提供するともっと正確な時間管理を楽しむスーパーコピーブルガリ 時計。シチズン技術を採用し、その光エコ・ドライブ電波吸収、いかなる光源に転化する運動エネルギーを時計運転すれば、光がエネルギーさえすれば、受信電波が自動補正時間、永遠にない誤差。スーパー空の鷹の特徴はそれより多く局受信標準時電波が、世界的に29タイムゾーン43都市より正確な時間によると、30分の時差を示しても、君がいるヨーロッパ、アメリカ、中国も日本所在都市名を選んで、現地時間の標準が自動受信電波が、正確に切り替えて現地時間。また、スーパー空の鷹はのJIS1型耐磁性能、衝突検出機能と指針修正機能、より正確にも挑戦させて恐れない、完璧な表現は一貫して、異郷の時間、方便用時計、れ、クロノカウントダウン、カウントダウン・充電喚起など多彩な機能に男はさらに対応父の後の新しい生活をよりを楽しみと幸福な人生旅;ORIS時計コピー人間化の現地時間騒ぎ響と異郷の時間が機能を問わず、父親たちの何処かで、いつでも注意しても、彼らについて子供のいかなる時間の詳細。[/url]

  19. VB says:

    I dont see anything changing in real time. Does this work?

  20. Florene says:

    If some one wishes to be updated with most recent technologies then he must be pay a visit this web page and be up to date
    everyday.

  21. I am really grateful to the owner of this web page who has shared this great article at
    at this time.
    Chung cư rivera park, chung cu rivera park, rivera park hà nội,
    rivera park ha noi

  22. פרזידנט אסקורט מציג נערות ושירותי סקס ליווי בתל אביב ומרכז ישראל.

  23. פרזידנט אסקורט מספק נערות ליווי פרטיות ברחבי כול ישראל להזמנה הביתה או לדירה הדיסקרטית שלכם.

  24. 1800800 מאפשר לגם להשכיר חדרים ודירות דיסקרטיות לפי שעה איפה שניתן לפגוש נערות ליווי בפרטיות מלא.

  25. Thank you for sharing. This is very useful and good information. I got more information from your site. Glad to see more post from you

  26. First off, your situation: You have poor credit and also you wish to use cards to develop
    a good credit rating ratings. So, what things to remember when hunting for a ton with a charge card online.
    The best plastic card is certainly one that applies and answers in your
    preference and lifestyle.

  27. S品N品コピーブランド時計激安通販専門店
    2017年人気最高品質時計コピー、国際ブランド腕時計コピー最新入荷!
    商品の数量は多い、品質はよい。
    海外直営店直接買い付け!
    製品はされています高品質と低価格で提供!歓迎新旧顧客お願いします!
    ★ 2017年注文割引開催中,全部の商品割引10%
    ★ 在庫情報随時更新!
    ★ 実物写真、付属品を完備する。
    ★ 100%を厳守する。
    ★ 送料は無料です(日本全国)!
    ★ お客さんたちも大好評です
    ★ 経営方針: 品質を重視、納期も厳守、信用第一!
    税関の没収する商品は再度無料にして発送します

  28. コピーモンクレール専門店
    当サイトはモンクレール全品(新品/スーパーコピー品)を
    販売しているの専業通販店舗です。
    主にモンクレールダウン、モンクレール ダウンジャケット、
    ダウンコート、ダウンベスト、モンクレールメンズ、
    モンクレールレディースを取り扱っています。

  29. FirstJoey says:

    I see you don’t monetize your page, don’t waste your traffic, you can earn additional cash every month because you’ve got hi quality content.
    If you want to know how to make extra bucks, search for: Boorfe’s tips best adsense
    alternative

  30. F*ckin?tremendous things here. I am very glad to peer your article. Thank you a lot and i’m taking a look forward to touch you. Will you kindly drop me a e-mail?

  31. Generally I do not learn post on blogs, but I wish to say that this write-up very forced me to try and do it! Your writing style has been surprised me. Thanks, very nice article.

  32. Fidel Means says:

    Hello there no-margin-for-errors.com

    SEO Link building is a process that requires a lot of time.
    If you aren’t using SEO software then you will know the amount of work load involved in creating accounts, confirming emails and submitting your contents to thousands of websites in proper time and completely automated.

    With THIS SOFTWARE the link submission process will be the easiest task and completely automated, you will be able to build unlimited number of links and increase traffic to your websites which will lead to a higher number of customers and much more sales for you.
    With the best user interface ever, you just need to have simple software knowledge and you will easily be able to make your own SEO link building campaigns.

    The best SEO software you will ever own, and we can confidently say that there is no other software on the market that can compete with such intelligent and fully automatic features.
    The friendly user interface, smart tools and the simplicity of the tasks are making THIS SOFTWARE the best tool on the market.

    IF YOU’RE INTERESTED, CONTACT ME ==> moneyrobotsubmitter@mail.com

    Regards, Fidel
    France, GUYANE, Le Tampon, 97430, 41 Rue Du General Ailleret

  33. Tali says:

    נערות ליווי מאשקלון

  34. taomiwersta says:

    website with musically hack 2019

    Maulydia musically hack 2019 had identified Tik Tok Sprightliness Hacks back Tik Tok but she however discovered the print of Tik Tok on someone’s social existence when she saw the weight on her preteen cousin.

  35. 秋冬おすすめの今年大人気なブランド コピー 激安 – KEEVOO http://www.keevoo.com/ シュプリーム コピー 通販パーカーは男性の若者にに大ファッションな一枚ですね。又、ジップアップ式で、頭から被せずに着れるので、とても便利ですね。

  36. hdtvku says:

    I’m impressed, I must say. Seldom do I come across a blog that’s
    both equally educative and entertaining, and let me
    tell you, you’ve hit the nail on the head.

    The issue is an issue that too few people are speaking intelligently about.
    Now i’m very happy that I came across this in my hunt for something relating to
    this.

  37. Patrickrer says:

    black and white gay dating
    gay chubs dating
    gay dating show audition logo

Leave a Reply