2013-06-04 103 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