Laravel socket.io транслирует всем, кроме отправителя

Я разрабатываю приложение Laravel с календарными событиями.

Я использую socket.io для трансляции событий (согласно уроку здесь: https://laracasts.com/lessons/broadcasting-events-in-laravel-5-1#)

мой файл socket.js:

var app = require('express')();

var http = require('http').Server(app);

var io = require('socket.io')(http);

var Redis = require('ioredis');

var redis = new Redis();

redis.subscribe('test-channel', function(err, count) {
    // 
});

redis.on('message', function(channel, message) {

    console.log('Message Received! ' + message);

    message = JSON.parse(message);

    io.emit(channel + ':' + message.event, message.data);
});

http.listen(3000, function() {
    console.log('Listening on *:3000');
});

Он работает нормально, но когда событие создается, оно возвращается отправителю и дублируется.

Я пытался использовать

socket.broadcast.emit(channel + ':' + message.event, message.data);

вместо того

io.emit(channel + ':' + message.event, message.data);

но сокет не определяется.

Есть ли способ сделать это, не отправляя идентификатор отправителя с событием, а затем вручную проверяя его в интерфейсе?


person viktorasv    schedule 03.09.2015    source источник
comment
Не понимаю, как дублируется мероприятие. Вы получаете сообщение от Redis и отправляете его через socket.io. Клиент отправляет данные на другой сервер (который вы не предоставили), который публикуется в Redis? И ваш сервер подписывается на Redis и отправляет сообщения с socket.io обратно клиентам?   -  person galethil    schedule 03.09.2015
comment
@galethil - встреча создается в представлении календаря (здесь мы используем DayPilot), а затем ее данные отправляются через ajax в Laravel. Laravel создает его в базе данных, запускает созданное событие, которое транслируется через redis, и всем, у кого открыто представление календаря (включая отправителя), при получении сообщения DayPilot добавляет встречу в представление. Так что в этом случае в представлении отправителя он дублируется.   -  person viktorasv    schedule 03.09.2015


Ответы (1)


Вы можете использовать это решение, но вам нужно иметь возможность отправить идентификатор отправителя в Laravel (при создании записи календаря), а затем опубликовать его в Redis. Также все клиенты должны отправлять свои идентификаторы на сервер socket.io.

На вашем сервере socket.io вы должны создать своего рода логин и базу данных клиентов. Например.:

var clients = {};

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

  //receive login event with login data {senderId:'YourSenderID'}
  socket.on('login', function(data){
    //save socket ID
    clients[data.senderId] = socket.id;
  });
});

После этого вы можете транслировать

redis.on('message', function(channel, message) {
  console.log('Message Received! ' + message);

  message = JSON.parse(message);

  //you need to have senderId here, then you can broadcast for every socket except the socket of calendar entry sender
  io.sockets.connected[clients[message.senderId]].broadcast.emit(channel + ':' + message.event, message.data);
});
person galethil    schedule 03.09.2015
comment
Спасибо, этот сработал, с добавлением: io.sockets.connected[clients[message.senderId]] - person viktorasv; 03.09.2015