Estoy tratando de enviar los mensajes del servidor al usuario final que ha iniciado sesión en nuestro sitio web del matraz.
Investigué un poco y parece que la mejor solución es usar socket-io.
Mis intentos de esto no parecen estar funcionando, también debo indicar que mi conocimiento de javascript es muy básico.
Cualquier ayuda / orientación será muy apreciada.
Ver mi código a continuación:
python - aplicación.py
from flask_socketio import SocketIO, emit from flask import Flask, render_template, url_for, request from time import sleep app = Flask(__name__) app.config['SECRET_KEY'] = 'secret' app.config['DEBUG'] = True # turn the flask app into a socketio app socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True) @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': if request.form['submit_button'] == 'Do Stuff': # server doing things.... # the below method will make calls to emit socket messages # based on actions / outcome of actions. serverActions() return render_template('index.html') @socketio.on('connect') def connect(): print('Client connected') @socketio.on('display_message') def displayMessage(message): socketio.emit('newmessage', {'message': message}) socketio.sleep(2) def serverActions(): # get connection to DB message = "connecting to DB" # show message to user on flask page displayMessage(message) # test successful connection to DB message = "successfully connected to DB" displayMessage(message) # query the DB message = "querying the DB" displayMessage(message) # update DB message = "updating the DB" displayMessage(message) # etc...... if __name__ == '__main__': socketio.run(app)HTML - plantillas/index.html
<!DOCTYPE html> <html> <head> <script src="//code.jquery.com/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script> <script src="static/js/application.js"></script> </head> <body> <form method="POST"> <div> <div> <h1>Asynchronous Flask Communication</h1> <p>Messages generated by the Flask server should appear below, asynchronously.</p> </div> </div> <div> <p>Asynchronous page updates will appear here:</p> <div> <input type="submit" value="Do Stuff" name="submit_button"> </div> <div> <h3>Server Messages:</h3> <div id="message"> </div> </div> </div> </form> </body> </html>javascript - estático/js/aplicación.js
$(document).ready(function(){ //connect to the socket server. var socket = io.connect('http://' + document.domain + ':' + location.port); //receive message details from server socket.on('display_message', function(msg) { console.log("Received message" + msg.message); message_string = '<p>' + msg.message + '</p>'; $('#message').html(message_string); }); });emit eventos que escucha con on controlador de eventos. Además, no creo que tenga sentido que su detector de eventos display_message esté dentro de un punto final de descanso. Aquí hay una solución con pypubsub por conveniencia para que pueda suscribirse fácilmente a todos los eventos en el servidor. También puede funcionar sin él, pero aquí está.
servidor.py
from flask_socketio import SocketIO, emit from flask import Flask, render_template, url_for, request from time import sleep from pubsub import pub app = Flask(__name__) app.config['SECRET_KEY'] = 'secret' app.config['DEBUG'] = True # turn the flask app into a socketio app socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True) def listener(arg1): print('Function listener1 received:') print(' arg1 =', arg1) socketio.emit('newmessage',{'message':arg1}) pub.subscribe(listener, 'rootTopic') @app.route('/', methods=['GET', 'POST']) def index(): return render_template('index.html') @app.route('/post', methods=['POST']) def post(): pub.sendMessage('rootTopic', arg1='post') @socketio.on('connect') def connect(): pub.sendMessage('rootTopic', arg1='connected to socket') print('Client connected') if __name__ == '__main__': socketio.run(app)índice.html
<!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="message"></div> <button id="btn">CLICK</button> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> $(document).ready(function(){ //connect to the socket server. var socket = io.connect('http://' + document.domain + ':' + location.port); $('#btn').on('click', function() { fetch('http://' + document.domain + ':' + location.port + '/post', {method:"POST"}) }) //receive message details from server socket.on('newmessage', function(msg) { console.log("Received message" + msg.message); message = '<p>' + msg.message + '</p>'; $('#message').append(message); }); }); </script> </body> </html>El problema del ejemplo que ha dado parece ser que el cliente, es decir, su JS en el navegador, está escuchando el evento display_message . Sin embargo, su servidor no está emitiendo ese evento por lo que parece. Cada llamada a displayMethod emite un evento de newmessage . Actualice su cliente para agregar un detector de eventos para ese evento.
socket.on('newmessage', function(msg) { console.log("Received message" + msg.message); message_string = '<p>' + msg.message + '</p>'; $('#message').html(message_string); });Aquí está el truco: emitir mensajes a un grupo. Por lo tanto, podría invocar unirse al grupo y agregar a todos a un grupo al iniciar sesión de esa manera, puede enviar mensajes a todos los conectados.
from flask import Flask from flask_socketio import SocketIO, send, emit, join_room, leave_room app = Flask('__name__') socket = SocketIO(app, cors_allowed_origins="*", SameSite=None) @socket.on('connect', namespace='/optional') def connect(): join_room('connected') @app.route('/message') def some_name(): emit('message', 'your actual message', room='connected', namespace='/optional')Ahora, cuando presione la URL, debería enviar un mensaje a todos los conectados. Recuerde que el espacio de nombres es opcional, pero le recomiendo que use uno.