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

node.js + socket.io + redis + rails — RealTime application

本文关键字:实时 应用程序 io+redis+rails js+socket node      更新时间:2023-09-26

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

我在后端(node.js(中有这个application.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);
});

我正在用node application.js命令启动application.js,它很有效!

MacBook Pro Zhirayr:rt Zhirayr$node application.js信息-socket.io启动

但当我尝试从Rails应用程序中使用redis($redis.publish'rt-change',{hello:'world'}(发送消息时,我的浏览器不会在控制台中记录任何内容。我确信,来自浏览器的连接已经建立,因为当我停止节点时,它会抛出连接拒绝错误。我确信redis和node之间的连接已经建立,这是因为application.js中的console.log(message(记录了它。但浏览器中的console.log不会记录任何内容。

有什么想法吗?

谢谢。

#Antoine 的UPD

在application.js中添加了console.logio.on("连接",函数(套接字({redis.on('message',函数(通道,消息({console.log('来自redis的新消息'(;socket.emit('rt-change',message(;});});

当r.publish"rt change"、{:hello=>"world"}被执行时,节点会记录以下内容:

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次日志。

 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事件,并添加给定的函数作为事件处理程序。只要有新用户连接,就会执行它。这将创建一个单独的作用域,用于每次执行处理程序。

当你呼叫这个

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在重新连接后再创建一个连接