node.js + socket.io + redis + rails – 实时应用程序

我需要将实时添加到我的应用程序(Ruby On Rails),所以我认为更好的方法是使用node.js + socket.io + redis。

我有这个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与节点application.js命令,它的工作原理!

MacBook-Pro-Zhirayr:rt zhirayr $ node application.js info – socket.io启动

但是当我试图从Rails应用程序发送redis消息($ redis.publish'rt-change',{hello:'world'})时,我的浏览器不会在控制台中logging任何东西。 我敢肯定,从浏览器build立连接,导致当我停止节点时,它抛出连接拒绝错误。 我确信redis和节点之间的连接已经build立,导致application.js中的console.log(消息)logging。 但浏览器中的console.log不会logging任何内容。

任何想法为什么?

谢谢。

UPD为#Antoine

在application.js中添加console.log io.on('connection',function(socket){redis.on('message',function(channel,message){console.log('redis'的新消息); socket。 emit('rt-change',message);});});

当r.publish'rt-change',{:hello =>'world'}被执行时,节点logging这个:

 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个消息节点logging11次。

  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> 

多次执行单个发布的原因是因为代码中嵌套的事件处理。 我会尽可能简单地解释这一点。

你打电话时

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

你监听connection事件,并添加给定的函数作为事件处理程序。 只要有新用户连接就会执行。 这将创build一个单独的作用域,以便每次执行处理程序。

当你打电话给这个

 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代码结构:在哪里放置方法?
  2. socket.io在重新连接后创build一个更多的连接