Search code examples
jquerypython-2.7socket.ioflask-socketioflask-sockets

SocketIO not receiving message in JS


I'm trying to implement a FlaskSocketIO with socket.io.js application for real-time communication between frontend and my web socket server

The frontend code looks like that:

 $(document).ready(function() {
        namespace = '/test';
        var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
        socket.on('connect', function() {
            socket.emit('my event', {data: 'Client connected!'});
        });
        socket.on('my response', function(msg) {
            $('#log').append('<br>' + $('<div/>').text('Received #' + msg.count + ': ' + msg.data).html());
        }); });

The code I'm using in Flask is:

@socketio.on('my event', namespace='/test')
def receive__message(message):
    socketio.emit('my response', {'data': 'Backend saw "' + json.dumps(message['data']) + '" from the frontend'})
    print("Received from message data:" + json.dumps(message['data']))

On the FlaskSocketIO side I can receive the message successfully but when I emit the 'my respose' message I can see the message listed inside the Network tab from Google Chrome like below but no action is taken according to my javascript code above for 'my response' event:

ÿ42["my response",{"data":"Backend saw \"{\"state\": \"Client Connected \"}\" from the frontend"}]

Having said that, the communication between frontend and flasksocketsio is successfully made but nothing happens on this portion of code ...

  socket.on('my response', function(msg) {
            $('#log').append('<br>' + $('<div/>').text('Received #' + msg.count + ': ' + msg.data).html());
        });

I've tried using alert(msg) or even console.log(msg) but they don't show me anything even I see the message received... Any clues what could be wrong? Maybe Flask generate the message in a wrong format for SocketIO JS plugin ?


Solution

  • There are two ways to emit messages from the server to the client.

    You are using the socketio.emit() function. This is a context independent function that knows nothing about the environment. In your example, you did not include the namespace argument, so the emit is getting sent to the client on the default namespace instead of on your /test namespace. If you add namespace='/test' your client will get the message just fine.

    An alternative way that is more convenient in this case is to use the context-aware emit() function. This can be used only from inside an event handler. This function obtains some information from the event context, for example, it detects what was the namespace used in the event currently being handled and defaults to emitting on the same namespace. That would be something like this:

    from flask_socketio import emit
    
    @socketio.on('my event', namespace='/test')
    def receive__message(message):
        emit('my response', {'data': 'Backend saw "' + json.dumps(message['data']) + '" from the frontend'})
        print("Received from message data:" + json.dumps(message['data']))
    

    One important difference between the context-aware and context-independent versions of emit is that the context-aware version will default to emitting back to the client that sent the originating event, while the context-independent emit will default to broadcasting to all clients, since it has no knowledge of the context.