2013-06-04 28 views
7

私のアプリケーション(Ruby On Rails)にリアルタイムで追加する必要があるので、これを行うより良い方法はnode.js + socket .io + redis。node.js + socket.io + redis + rails - RealTimeアプリケーション

私は、これは私がノード・アプリケーションとのapplication.jsを起動してい

var socket = io.connect('http://localhost:5001/socket.io'); 
socket.on('rt-change', function (data) { 
    console.log(data); 
}); 

(Node.jsの)

var app = require('http').createServer(); 
var io = require('socket.io'); 
var redis = require('redis').createClient(); 
var _ = require('underscore')._; 

io = io.listen(app); 
io.configure(function() { 
    io.set("transports", ["xhr-polling"]); 
    io.set("polling duration", 10); 
    io.set("close timeout", 10); 
    io.set("log level", 1); 
}) 

redis.subscribe('rt-change'); 

io.on('connection', function(socket) { 
    redis.on('message', function(channel, message) { 
     socket.emit('rt-change', message) 
    }); 
}); 

var port = process.env.PORT || 5001; 
app.listen(port); 

そしてmessages.jsフロントエンドでのバックエンドでファイルをapplication.js持っています.jsコマンドを入力してください。

のMacBook - プロZhirayr:室温zhirayrの$ノードが情報をapplication.js - socket.ioは

を始めたしかし、私はRedisの($のredis.publish「RTでメッセージを送信しようとしているとき-change '、{hello:' world '})を実行すると、ブラウザはコンソールに何も記録しません。 ブラウザからの接続が確立されていることを確認します。ノードを停止すると、接続拒否エラーがスローされます。また、redisとノードの接続が確立されていると確信しています。これによって、application.jsのconsole.log(メッセージ)がログに記録されます。 ブラウザのconsole.logには何も記録されません。

なぜでしょうか?

ありがとうございました。 application.js io.on( '接続'、関数(ソケット){ redis.on( 'メッセージ'、機能(チャンネルメッセージ){で#Antoine

追加しましたにconsole.logため

UPD console.log( 'redisからの新しいメッセージ'); socket.emit( 'rt-change'、message); }); }); r.publish '変更を室温'

:実行なっ{ハロー=> '世界'}、ノードはこれを記録します。

new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 
new message from redis 

それは1つのメッセージの奇妙、ノードログを11回です。

+0

はどこからすると、このメッセージが ' '変更を室温'、{ハロー$ redis.publishを送信します} '? – udidu

+0

Railsアプリから。 –

+1

redis subscribeコールバックにログを記録して、トリガされていることを確認できますか? – Antoine

答えて

11
var socket = io.connect('http://localhost:5001/socket.io'); 
socket.on('rt-change', function (data) { 
    console.log(data); 
}); 

このコードの一部は、次のように何かを行う必要があります 、http://socket.io上のドキュメントによると、正しいいないようです:あなたは、単一のために複数の実行を取得している理由は、公開

<script src="http://localhost:5001/socket.io/socket.io.js"></script> 
<script> 
    var socket = io.connect('http://localhost:5001'); 
</script> 
+0

自分で解決する10分前に、私はチケットを閉じるためにstackoverflowにジャンプし、ここにあなたは答えです:)とにかくおかげで。 –

5

あなたのコードでネストされたイベント処理が原因です。私はできるだけ簡単にこれを説明しようとします。

あなたは

io.on('connection', function(socket) {...}); 

を呼び出すときにconnectionイベントをリッスンし、イベントハンドラとして与えられた関数を追加します。新しいユーザーが接続するたびに実行されます。これにより、毎回ハンドラを実行するための別のスコープが作成されます。

あなたはこの

io.on('connection', function(socket) { 
    redis.on('message', function(channel, message) { 
     console.log('new message from redis'); 
     socket.emit('rt-change', message); 
    }); 
}); 

を呼び出すと、あなたが個別に接続しているユーザのそれぞれについて、Redisの加入イベントmessageのリスナーを追加します。このため、複数のログを取得しており、接続しているユーザーは同じメッセージの複数のコピーを取得します。 11のメッセージがあり、そのときに11人の異なるユーザーが接続していたことを意味します。

これを解決するには、リスニングイベントではonの代わりにonceと電話することができます。このように

io.once('connection', function(socket) { 
    redis.on('message', function(channel, message) { 
     console.log('new message from redis'); 
     socket.emit('rt-change', message); 
    }); 
}); 

これはsocket.ioクライアントにも当てはまります。この上の明快さを得るために、私の以前の回答を参照してください:「世界:

  1. socket.io code structure: where to place methods?
  2. socket.io creates one more connection after reconnecting
関連する問題