そろそろnode.jsを触っておかないとダメかなと思って、nowjsってのを使ってみた日記

ブクマをさかのぼっていてnowjsってのを思い出したので使ってみることにした。
nowjs for Node - Directly call remote functions in Javascript

公式サイトを見ると、nowjsはクライアントとサーバ側で互いにメソッドを呼び合うことができ、12行でリアルタイムチャットが作れるらしい。12行って簡単すぎわろた。
というわけで今回はnowjsの導入と、サンプルを動かし、サンプルコードの中身を見てわかったことをメモっておく。

準備

naveを使ったnode.jsインストールと、最近のnpmの使い方 - ラシウラ

上記URLを参考に、naveとnpmをインストールする。
ただしnodeの最新版を入れると0.5系が入ってしまい、nowjs*1が動かないので、安定板の0.4.11を入れてnpmもインストールする。

$ nave use 0.4.11
$ curl http://npmjs.org/install.sh | sh

nowjs用のディレクトリを作って、そこにnpmでnowjsに必要なライブラリをインストールする。
nowjsについてくるexampleを動かすために、express(Sinatraっぽいやつ)とels(ERB的なテンプレートエンジン)を入れる。

$ npm install now
$ npm install express
$ npm install ejs

インストールしたらそのディレクトリ以下に node_modulesというディレクトリができていて、その中にnowjsの本体とexampleが入っているので、それを動かしてみる。

$ cd node_modules/now/examples/express_example
$ node app.js

これで http://localhost:8080/ にアクセスすればチャットを試せます。ChromeSafariだとwebsocketでアクセスしてるみたいだけど、他のブラウザだとcometみたいにずっとリクエストし続けてた。これはnowjsを入れたときに一緒に入るsocket.ioがなんかやってるのかな?

express_exampleの他にサンプルが2つあるけど、express_exampleを選んだのは一番コードが単純だから。というわけで今回はこのexpress_exampleのコードを見ながらどういう風に動いてるのか見ていきたいと思う。

サーバ側

先にサーバ側のコード(app.js)を見る
30行目まではexpressのコードなので無視する。重要なのは30行目以降

// NowJS component
var nowjs = require("now");
var everyone = nowjs.initialize(app);

これはnowjsの準備。とりあえず書いとく。

>|javascript||
nowjs.on('connect', function(){
console.log("Joined: " + this.now.name);
});
nowjs.on('disconnect', function(){
console.log("Left: " + this.now.name);
});
|

これはサーバに接続した(または抜けた)時にコールバックされる。例えばチャットを作るのであれば、接続時に「〜さんがオンラインになりました」と表示したりだとか、接続中のユーザーを保存して「現在オンラインのユーザーを表示」みたいなことができるかなと。disconnectの方は逆のことができますね。

everyone.now.distributeMessage = function(message){
  everyone.now.receiveMessage(this.now.name, message);
};

これはdistributeMessageという関数を定義している。
this.now.nameはクライアント側のJSで定義した変数。receiveMessageというメソッドはクライアント側で定義したメソッドを呼び出している。

クライアント側

クライアント側は/nowjs/now.jsというファイルをまず読み込んでいる。
このファイルはサーバを起動したときに作られるっぽい。
メインのコードはchat.ejsにある

<script>
    $(document).ready(function(){
      now.receiveMessage = function(name, message){
        $("#messages").append("<br>" + name + ": " + message);
      }
      $("#send-button").click(function(){
        now.distributeMessage($("#text-input").val());
        $("#text-input").val("");
        $("#text-input").focus();
      });
      now.name = prompt("What's your name?", "");
    });
</script>

now.nameのように定義すると、サーバ側と変数を共有できる。サーバ側ではnow.nameではなくthis.nameで参照する。
now.distributeMessage()とやると、サーバ側で先程定義したメソッドが呼び出せる。
now.receiveMessage = のように関数を定義しておくと、サーバ側で呼び出すことが可能になる。
クライアント側からサーバ側の関数を、サーバ側からクライアント側のコードを直接叩けばいいので、ajaxのリクエストみたいにコールバック指定したりいろいろする必要がなくてすっきりしますね!

まとめ

12行でリアルタイムチャットができるのは確かにすごいんだけど、nowjsの便利なところはクライアントとサーバ側でメソッドをお互いに呼び出しあったり、変数を共有できたりするところにあるのかなと思った。他のexampleには部屋を作ってグループチャットをするものも含まれていたし、これを使えばLingrみたいなのは意外と簡単に作れそうな気がした。
あとRailsアプリにnowjsを使ってリアルタイムに通知するみたいなのを遊びで実装してみたけど、railsとnodeでポート番号が違うせい(?)でクロスドメイン制約に引っかかったのか(または自分のプログラムが悪いのか)Firefoxで動かなかったりしたし、サーバ側がRailsなのに新しくnode.jsを立てるのはどうなのとか、運用さんにまた新しい仕事を頼むほどのメリットも感じなかったので諦めた。
というわけで全部JSで何らかのサービスを作ってみたくなったのでした。

*1:正確にはnode-proxy?