Socket io Nodejs-当用户打开多个选项卡时进行pipe理

我试图在我的应用程序中写一个聊天,我有一个问题,不知道如何pipe理它! 这里是senario:我们有许多用户是authenricated所以他们都有一个唯一的ID,我想实现像Facebook这样的聊天,所以每两个用户可以相互聊天。 为此,我有一个server.js文件的内容:

var app = require('express')(); var server = require('http').Server(app); var io = require('socket.io')(server); var redis = require('redis'); var users = []; server.listen(8890); io.on('connection', function (socket) { console.log("client connected"); var redisClient = redis. redisClient.subscribe('message'); redisClient.on("message", function(channel, data) { var data = JSON.parse(data); socket.to('user_'+data.user).emit(channel, data); }); // join a room socket.on('newUser',function (user, type){ socket.type = type; socket.join('user_'+user); }); }); 

和一个client.js:

 var socket = io.connect( 'http://127.0.0.1:8890' ); if (auth) { socket.on('connect', function(){ socket.emit('newUser', userId, userType); }); } socket.on( 'message', function( data ) { console.log(data); // var data = JSON.parse(data); var content = $( "#messages" ).html(); var newMsgContent = '<li>' + data.message + '</li>'; var newContent = newMsgContent + content; $( "#messages" ).html( newContent ); }); 

消息的forms将与以下内容一起发送:

 <form action="{{ route('message.send') }}" method="POST" class="ajax-form"> <input name="_method" value="put" type="hidden"/> <input name="user" value="{{ $user }}" type="hidden"/> <input name="item" value="{{ $item }}" type="hidden"/> <input name="type" value="{{ $type }}" type="hidden"/> <input name="socketId" value="" type="hidden"/> <input name="message" value="message to {{ $user }} from {{ @$requirements->user->id }}" type="text" class="input-xxlarge" placeHolder="Message" /> <br> <input type="submit" value="Send" /> </form> 

最后Redis会发送这个消息:

 $redis = \LRedis::connection(); $data = ['user' => $request->user, 'message' => $request->message]; if($redis->publish('message', json_encode($data))) return true; 

在上面的代码中,当用户打开我的应用程序时,会使用一个连接,newUser将会启动,所以我用这个ID为这个用户创build了一个空间,然后把它连接到这个房间(socket.join('user _'+ user))。 然后,当一个用户想要发送一个消息给这个用户时,我简单地发送一个接收者用户的ID(我们之前为他创build了一个房间),然后把这个消息发送到这个Id所在的房间(socket.to('user_' + data.user).emit(channel,data);)。 问题是,当一个用户打开多个标签时,他们每个人都被认为是一个用户,并将与另一个socket.id连接到同一个房间,但都是具有唯一ID的用户! 然后,当我向有两个选项卡打开的用户发送消息时,他将从一个请求中获得2条消息! 如:你好ID 5你好ID 5

所以,现在我该怎么做才能将每​​个标签的消息发送到用户打开的所有标签页! 提前致谢。

将您的redisCLient.subscribe移动到连接侦听redisCLient.subscribe外部。 每次build立连接时,都会再次附加事件,这就是为什么您要重复的原因。

 var redisClient = redis.createClient(); redisClient.subscribe('message'); redisClient.on("message", function(channel, data) { var data = JSON.parse(data); //Changed socket.to with io.to io.to('user_'+ data.user).emit(channel, data); }); io.on('connection', function (socket) { console.log("client connected"); // join a room socket.on('newUser',function (user, type){ socket.type = type; socket.join('user_'+user); }); }); 

作为一个方面说明,您的客户端代码可以使用append进行改进

 socket.on( 'message', function( data ) { console.log(data); // var data = JSON.parse(data); $( "#messages" ).append('<li>' + data.message + '</li>'); });