2013-06-04 132 views
7

我需要將實時添加到我的應用程序(Ruby On Rails),所以我認爲更好的方法是使用node.js + socket .io + redis。node.js + socket.io + redis + rails - 實時應用程序

我有這樣的application.js文件在後端(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在前端

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

我啓動與節點應用的application.js .js命令,它的工作原理!

的MacBook-PRO-Zhirayr:RT zhirayr $節點的application.js信息 - socket.io開始

但是當我試圖用Redis的發送消息($ redis.publish「RT -change',{hello:'world'}),我的瀏覽器不會在控制檯中記錄任何東西。 我確定,從瀏覽器建立的連接導致當我停止節點時,它會拋出連接拒絕錯誤。我確信redis和節點之間的連接已經建立,導致application.js中的console.log(消息)記錄它。 但瀏覽器中的console.log不會記錄任何內容。

任何想法爲什麼?

謝謝。

UPD爲#Antoine

新增的console.log中的application.js io.on( '連接',函數(插座){ redis.on( '信息',函數(信道,消息){ ('來自redis的新消息'); socket.emit('rt-change',message); });; }); }

當r.publish 'RT-變化',{:你好=> '世界'}成爲執行時,節點記錄此:

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 

奇怪,節點記錄11次爲1個消息。

+0

您從哪裏發送此消息'$ redis.publish 'RT-變化',{你好: '世界' ''? – udidu

+0

從Rails應用程序。 –

+1

你可以在redis訂閱回調中加入一個日誌來確保它被觸發嗎? – 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個不同的用戶。

要解決此問題,您可以撥打once而不是on進行收聽活動。像這樣

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