pythonflasksocket.iopython-asynciobinance

frontend not displaying data emitted from socketio in real-time


my websockets app sends data fom the backend to the frontend. but it only updates whenever i refesh the page ,not real-time . I want the updating to be real time

my websockets app sends data fom the backend to the frontend. but it only updates whenever i refesh the page ,not real-time . I want the updating to be real time

below are my current implementations app.py:


import threading
import asyncio
from binance import AsyncClient, BinanceSocketManager
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from queue import Queue

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

# Queue to pass data from WebSocket threads to Flask main thread
data_queue = Queue()

# Function to handle Binance WebSocket stream
async def stream_btcusdt_data(client):
    bm = BinanceSocketManager(client)

    async with bm.trade_socket("BTCUSDT") as stream:
        while True:
            try:
                res = await stream.recv()
                data_queue.put(res)  # Put data into the queue
            except Exception as e:
                print(f"Error receiving data: {e}")

# Function to start WebSocket stream in a separate thread
def start_stream_thread():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    client = loop.run_until_complete(AsyncClient.create())
    loop.create_task(stream_btcusdt_data(client))
    loop.run_forever()

# Route to render HTML template
@app.route('/')
def index():
    return render_template('index.html')

# Function to read data from the queue and emit it to clients
def emit_data():
    while True:
        if not data_queue.empty():
            data = data_queue.get()  # Get data from the queue
            print("Data emitted:", data)  # Debugging statement
            socketio.emit('btcusdt_data', data, namespace='/')  # Emit data to clients

if __name__ == '__main__':
    # Start WebSocket stream thread
    stream_thread = threading.Thread(target=start_stream_thread)
    stream_thread.daemon = True
    stream_thread.start()

    # Start emit data thread
    emit_thread = threading.Thread(target=emit_data)
    emit_thread.daemon = True
    emit_thread.start()

    # Start Flask-SocketIO server
    socketio.run(app, debug=True)

index.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Binance WebSocket Stream</title>
    <script src="https://cdn.socket.io/4.7.4/socket.io.min.js" integrity="sha384-Gr6Lu2Ajx28mzwyVR8CFkULdCU7kMlZ9UthllibdOSo6qAiN+yXNHqtgdTvFXMT4" crossorigin="anonymous"></script>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const socket = io();  // Connect to WebSocket server

            // Function to log data to the console
            const logDataToConsole = (data) => {
                console.log(data);
            };

            // Listen for 'btcusdt_data' events from the server
            socket.on('btcusdt_data', (data) => {
                // Log the received data to the console
                logDataToConsole(data);
            });
        });
    </script>
</head>
<body>
    <h1>Binance WebSocket Stream</h1>
    <!-- This div is not used for displaying data as we're logging to the console -->
    <div id="data-container"></div>
</body>
</html>

I feel the issue is from the frontend, but the code seems okay.


Solution

  • The problem is in both - front end and back end. When you are creating socketio instance of SocketIO, it is good to enable cors:

    socketio = SocketIO(app, cors_allowed_origins="*")
    

    On the front end, when there is creation of connection to socket, the URL to the socket have to be provided:

     const socket = io("http://127.0.0.1:5000")
    

    In my case it is on port 5000 with local IP 127.0.0.1, in other PCs and configurations can be different.