Как удалить сообщение у всех пользователей, используя socket.io ?

#mysql #sockets #socket.io

#mysql #сокеты #socket.io

Вопрос:

Я использую сокет.ввод-вывод и mysql (сервер узла)

Но я не добился успеха в функции удаления.

Вот что у меня есть и что я пробовал до сих пор

 io.on('connection', (socket) => {
    connection.query("SELECT * FROM `messages`", (err, data) => {
        for(let x in data) socket.emit('message', { id: data[x].message_id, text: data[x].message })
    })
    socket.on('disconnect', () => {
        // console.log('user disconnected');
    })

    socket.on('add-message', (message) => {
        addMessage(message, (res) => {
            if(res) io.emit('message', { type: 'new-message', text: message}); 
        })
    });

    socket.on('delete-message', (id) => {
        connection.query("DELETE FROM `messages` WHERE `message_id` = '"  id  "'");
        io.emit('message', { type: 'delete-message', id: id }) // broadcast that something has changed
    })
})
  

Служба Angular2

 import { Subject } from 'rxjs/Subject'
import { Observable } from 'rxjs/Observable'
import * as io from 'socket.io-client'

export class ChatService {
    private url = 'http://localhost:5000'
    private socket;

    sendMessage(message) {
        this.socket.emit('add-message', message);    
    }

    getMessages() {
        let observable = new Observable(observer => {
            this.socket = io(this.url);
            this.socket.on('message', (data) => {
                observer.next(data);
            });

            return () => {
                this.socket.disconnect();
            };  
        })

        return observable;
    }

    deleteMessage(id) {
        this.socket.emit('delete-message', id);
    }
}
  

Компонент

 export class AppComponent implements OnInit, OnDestroy {
    messages = []
    connection;
    message: any;

    constructor(private chatService: ChatService){ }

    sendMessage(): void {
        this.chatService.sendMessage(this.message);
        this.message = '';
    }

    ngOnInit() {
        this.connection = this.chatService.getMessages().subscribe(message => {
            this.messages.push(message);
        })
    }

    ngOnDestroy() {
        this.connection.unsubscribe();
    }

    deleteData(id): void {
        for(var i = 0; i < this.messages.length; i  ) {
            if(this.messages[i].id == id) {
                this.messages.splice(i, 1)
                this.chatService.deleteMessage(id)

                break;
            }
        }
    }
}
  

Проблема в том, что я пробовал:

Для deleteData() пользователь, который нажал кнопку удаления, будет иметь желаемый вид. Но для других пользователей они должны обновляться для обновленных данных.

Любая помощь будет оценена. Спасибо.

Ответ №1:

Во-первых, имейте в виду, что вам нужно сохранить все ваши данные в массив сообщений.

Сложная часть — message_id. Поскольку вы не можете присвоить ему значение. Предполагая, что у него есть авто_инкремент. Нам нужно добавить еще один столбец таблицы, который будет иметь уникальное значение.

Для моего примера я буду использовать message_identifier

В таблице будет (message_id, message_content, message_identifier)

Чтобы сохранить это коротким. у message_identifier будет просто время, которое преобразуется в миллисекунды (я полагаю). Вы должны создать метод, который сделает его совершенно другим.

На вашем СЕРВЕРЕ

Получение предыдущих сообщений

 connection.query("SELECT * FROM `messages`", (err, data) => {
    for(let x in data) socket.emit('message', { type: 'get-messages', message: data[x].message, identifier: data[x].identifier })
}
  

Добавление сообщения

 socket.on('add-message', function(message, identifier) {
    connection.query("INSERT INTO `messages` (`message_content`, `message_identifier`) VALUES ('"  message  "', '"  identifier  "')", (err) => {
        if(!err) io.emit('message', { type: 'new-message', message: message, identifier: identifier })
    })
})
  

Удаление сообщения

 socket.on('delete-message', function(identifier) {
    connection.query("DELETE FROM `messages` WHERE `message_identifier` = '"  identifier  "'", (err) => {
        if(!err) io.emit('message', { type: 'delete-message', identifier: identifier })
    });
})
  

Логика будет на компоненте. Вам просто нужно прослушать «сообщение» и определить по типу, который передает запрос.

Итак, вот оно:

Импорт сокета.ввод-вывод и наблюдаемый и объявляющий сокет на вашем компоненте.

 import * as io from 'socket.io-client'
import { Observable } from 'rxjs/Observable'

private socket = io(/* url of server */); // inside AppComponent
  

В вашем классе AppComponent. Вам нужно прослушать «сообщение»

 let data$ = new Observable(observer => {
    this.socket.on('message', (data) => {
        if(data.type == 'get-message' || data.type == 'new-message') {
            observer.next({ message: data.message, identifier: data.identifier })
        } else if(data.type == 'delete-message') {
            for(let i = 0; i < this.messages.length; i  ){
                if(parseInt(this.messages[i].identifier) == data.identifier){
                    this.messages.splice(i, 1);
                    break;
                }
            }
        }

        console.log(data)
    })
})

data$.subscribe(value => {
    this.messages.push(value);
})
  

Вы можете поместить это в ngOnInit или constructor. Я считаю, что это должно сработать либо из этих двух.

На вашем СЕРВИСЕ

Просто удалите GetMessages, поскольку мы обрабатываем его на компоненте.

Надеюсь, это поможет. Приветствия!

Комментарии:

1. Ууууу. Спасибо. Сработало как шарм.

Ответ №2:

Вы отправляете сообщение от клиента на ваш сервер nodejs для удаления сообщения. Однако, что вы забываете на стороне сервера, так это обновить все другие клиенты, чтобы что-то изменилось. В вашем ‘socket.on («delete-message»)’ вы также должны отправлять сообщения всем подключенным пользователям, чтобы уведомить их, что что-то изменилось. Вы можете сделать это аналогично добавлению сообщения:

  io.emit('message', { type: 'delete-message', id: id});
  

Кстати: оформить заказ ngrx / store. Это реализация Redux для angular 2. Если вы работаете с ngrx / store, вы определяете действия. Действия предназначены для обновления состояния на стороне клиента. Если бы вы использовали это, вы могли бы просто определить действие ‘DELETE_MESSAGE’ и отправить это действие через ваш сокет с сервера на клиент. Клиент просто отправит это действие в ngrx, и ваш пользовательский интерфейс будет хорошо обновлен :).

Комментарии:

1. Да, я знаю io.emit. Я писал это раньше, но моя проблема в том, как мне обновить сообщение. Очистите объект массива сообщений, затем попробуйте снова получить сообщения из БД? Сначала я попробую ngrx / store. Уггггг, наш инструктор не учит нас, как использовать websockets :/