最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - node.js + socket.io + redis + rails — RealTime application - Stack Overflow

programmeradmin3浏览0评论

I need to add realtime to my application (Ruby On Rails), so, I think that the better way to do it is to use node.js + socket.io + redis.

I have this application.js file in a backend (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);

And messages.js in frontend

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

I'm launching application.js with node application.js mand and it works!

MacBook-Pro-Zhirayr:rt zhirayr$ node application.js info - socket.io started

But when I'm trying to send message with redis ($redis.publish 'rt-change', {hello:'world'}) from Rails application, my browser doesn't log anything in console. I'm sure, that connection from browser established, cause when I stop node, it throws connection refused error. And I'm sure that connection between redis and node established, cause console.log(message) in application.js logs it. But console.log in browser doesn't log anything.

Any ideas why?

Thanks.

UPD for #Antoine

Added console.log in application.js io.on('connection', function(socket) { redis.on('message', function(channel, message) { console.log('new message from redis'); socket.emit('rt-change', message); }); });

When r.publish 'rt-change', {:hello=>'world'} bee executed, node logs this:

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

It's strange, node logs 11 times for 1 message.

I need to add realtime to my application (Ruby On Rails), so, I think that the better way to do it is to use node.js + socket.io + redis.

I have this application.js file in a backend (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);

And messages.js in frontend

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

I'm launching application.js with node application.js mand and it works!

MacBook-Pro-Zhirayr:rt zhirayr$ node application.js info - socket.io started

But when I'm trying to send message with redis ($redis.publish 'rt-change', {hello:'world'}) from Rails application, my browser doesn't log anything in console. I'm sure, that connection from browser established, cause when I stop node, it throws connection refused error. And I'm sure that connection between redis and node established, cause console.log(message) in application.js logs it. But console.log in browser doesn't log anything.

Any ideas why?

Thanks.

UPD for #Antoine

Added console.log in application.js io.on('connection', function(socket) { redis.on('message', function(channel, message) { console.log('new message from redis'); socket.emit('rt-change', message); }); });

When r.publish 'rt-change', {:hello=>'world'} bee executed, node logs this:

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

It's strange, node logs 11 times for 1 message.

Share Improve this question edited Jun 5, 2013 at 20:17 Mark Pegasov asked Jun 4, 2013 at 10:37 Mark PegasovMark Pegasov 5,2899 gold badges28 silver badges31 bronze badges 4
  • From where do you sending this message $redis.publish 'rt-change', {hello:'world'} ? – udidu Commented Jun 4, 2013 at 15:34
  • 1 Can you put a log into the redis subscribe callback to make sure that it's triggered ? – Antoine Commented Jun 4, 2013 at 21:38
  • Do you have any errors in your javascript console on the browser ? – Antoine Commented Jun 6, 2013 at 17:19
  • Have you tried sending message from node application.js? Put some socket.emit('rt-change', message) inside onConnection callback. Also are you 100% sure there is connection between browser and node app? You set transport to xhr-polling, so in console you should see "heartbeats". – ogur Commented Jun 6, 2013 at 17:51
Add a ment  | 

2 Answers 2

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

This part of the code does not seem correct, according to the doc on http://socket.io , you should do something like:

<script src="http://localhost:5001/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost:5001');
</script>

The reason why you are getting multiple executions for a single publish is because of the nested event-handling in your code. I will try to explain this as simple as I can.

When you call

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

you listen for connection event and add the given function as event handler. It is executed whenever a new user connects. This creates a separate scope, for the execution of the handler each time.

When you call this

io.on('connection', function(socket) {
    redis.on('message', function(channel, message) {
        console.log('new message from redis');
        socket.emit('rt-change', message);
    });
});

you add listeners for redis subscriber event message for each of the connected users separately. This is why you are getting multiple logs and connected users get multiple copies of same message. You got 11 messages which means there were 11 different users connected at that time.

To solve this you can call once instead of on for listening events. Like this

io.once('connection', function(socket) {
    redis.on('message', function(channel, message) {
        console.log('new message from redis');
        socket.emit('rt-change', message);
    });
});

This applies to the socket.io clients also. See my previous answers to get clarity on this:

  1. socket.io code structure: where to place methods?
  2. socket.io creates one more connection after reconnecting
发布评论

评论列表(0)

  1. 暂无评论