【问题标题】:node.js + socket.io + redis + rails — RealTime applicationnode.js + socket.io + redis + rails — 实时应用
【发布时间】:2013-05-30 17:17:59
【问题描述】:

我需要为我的应用程序(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 info - socket.io 启动

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

有什么想法吗?

谢谢。

#Antoine 的 UPD

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

当 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

很奇怪,1条消息节点记录了11次。

【问题讨论】:

  • 你从哪里发送这个消息$redis.publish 'rt-change', {hello:'world'}
  • 能否在redis订阅回调中加入日志以确保触发?
  • 浏览器上的 javascript 控制台是否有任何错误?
  • 您是否尝试过从 node application.js 发送消息?在 onConnection 回调中放入一些 socket.emit('rt-change', message)。您还 100% 确定浏览器和节点应用程序之间存在连接吗?您将传输设置为 xhr-polling,因此在控制台中您应该会看到“心跳”。

标签: javascript node.js socket.io


【解决方案1】:
 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>

【讨论】:

  • 10分钟前自己解决了,然后我跳到stackoverflow关闭票,这是你的答案:)还是谢谢。
【解决方案2】:

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

当你打电话时

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 2012-08-12
    • 2011-04-19
    相关资源
    最近更新 更多