Flask SocketIO Emit with broadcast = true не отправляет сообщение отправителю - PullRequest
2 голосов
/ 22 апреля 2020

Первый постер здесь. Я пытаюсь собрать приложение для чата, используя Flask -SocketIO, и мне трудно найти один крошечный, но важный элемент для работы. Когда я вызываю метод emit на сервере и устанавливаю флаг broadcast = True, ожидаемое поведение состоит в том, что он запускает соответствующие события socket.on на стороне клиента для всех пользователей, включая отправителя. Однако мой код, очевидно, делает это только для всех клиентов, кроме отправителя. Это противоречит документации на https://flask-socketio.readthedocs.io/en/latest/, где говорится:

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

Мне нужно для этого отправить сообщение и вызвать событие socket.on как для отправителя, так и для всех других клиентов. , Кто-нибудь может объяснить, что я здесь делаю не так? Потому что кажется, что такая базовая функция c, что я должен упустить что-то действительно очевидное.

Код сервера:

import os
import requests

from flask import Flask, jsonify, render_template, request
from flask_socketio import SocketIO, emit, join_room, leave_room

app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
socketio = SocketIO(app)

channels = ['a', 'b', 'c', 'testing', 'abc', '123']
ch_msgs = {'a': ['testing', '1234', 'high five'], 'b': ['hello']}
msg_limit = 100

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('add channel')
def add(data):
    new_channel = data
    channels.append(new_channel)
    ch_msgs[new_channel] = list()

    emit('announce channel', new_channel, broadcast=True)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

Javascript:

document.addEventListener('DOMContentLoaded', () => {

    var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);

    socket.on('connect', () => {

        document.querySelector('#add_channel').onclick = () => {

            const new_channel = document.querySelector('#new_channel').value;

            socket.emit('add channel', new_channel);

        };


    });

    socket.on('announce channel', data => {

        const li = document.createElement('li');

        li.innerHTML = '#' + `${data}`;

        $('#channel_list').append(li);

    });
});

HTML / CSS фрагмент:

<h3>Chat Channels</h3>
<br>

<ul id='channel_list' style='list-style-type:none;'>
</ul>

<form class='channel'>
     <input type='text' id='new_channel' placeholder='add new channel'><input type='submit' id='add_channel' value='Add'>
</form>

1 Ответ

1 голос
/ 22 апреля 2020

Фактически все клиенты получают отправленное сообщение, включая отправителя, но проблема здесь в том, что страница отправителя обновляется сразу после отправки формы (что является поведением форм по умолчанию), что приводит к потере все локальные данные.

Чтобы предотвратить это, вам нужно использовать метод event.preventDefault(). В вашем случае вы можете изменить обработчик события connect, например:

socket.on('connect', () => {
    document.querySelector('#add_channel').onclick = event => {
        event.preventDefault();
        const textinput = document.querySelector('#new_channel')
        const new_channel = textinput.value;
        textinput.value = "";    // Clear input after value is saved
        socket.emit('add channel', new_channel);
    };
});
...