Asynchronous execution problem on node server with Express, MySQL and Socket.IO

2

I'm developing a project on Node.JS with Express, MySQL and Socket.IO. When the user opens the main page provided by the server, the request must cause data to be read from the database and sent to the client for it to be listed on the page.

The problem is that before the data can be sent, the server sends the page to the client and this causes the data not to be read from the BD or sent to the socket. I tried using async to make all the functions run in order, but it did not work.

My code:

app.all("/", function(req, res){ //Função para qualquer requisição HTTP (GET ou POST)

    var query1 = 'SELECT ? FROM tabela1;', query2 = 'SELECT ? FROM tabela2;';

    function qSelect(callback, queryTxt){ //Realiza queries de seleção no bd
        db.query(queryTxt, ['*'], function(err, results){
            if(err){
                console.log("Error on:");
                callback();
                return null;
            }
            callback();
            return results;
        });
    }

    async.series( //Executa comandos em série
        [qSelect(console.log("Table 1 data query."),query1), 
         qSelect(console.log("Table 2 data query."),query2),
         sendDataClient(console.log("Data sent to client."))], 

        function (err, output){ //Função executada após funções enfileiradas em série

            if(err){
                console.log("Error!! Sending database data to client did not result in success.");
                data = [null, null];
            } else{
                data = output;
            }

            io.on("connection", function(callback, socket){
                socket.emit("appData", {msg: "Schedule and Contact Data", content: data});
                socket.on("Return", function (data){
                    console.log(data.content);
                });
            });

        }

    );

res.sendFile("index.html"); //Envia página html ao cliente

});

In case I use Express exclusively to handle http pages and requests. Socket.IO is for sending binary or text data to be used in javascript on the client side.

    
asked by anonymous 12.08.2015 / 16:27

2 answers

1

I think this mix of invoking io.on ("connection", ...) inside the app.all () handler is wrong.

One thing is for Express to serve the page; the other is the Socket.IO serving its requisitions. These are things that do not mix. Probably the client is attempting to connect Socket.IO before you have run io.on ("connection", ...) on the server side and then the connection has already failed.

You probably wanted to start the query already while loading the index.html, before the Socket.IO connection, but for what? Maybe win a few milliseconds?

The app.all (...) block should just send the index.html. Move all io.on ("connection", ...) block out of the app.all (...).

Async.series (...) must be invoked inside the io.on ("connection", ...) block, that is, you only query MySQL when the Socket.IO connection is actually made, and socket.emit () is the last step.

The socket.on ("Return", ...) must be called before async.series (...) because the client can again send the Return before you have configured the respective handler, and the message is lost.

    
12.08.2015 / 21:59
1

I ended up solving my problem myself. After trying Q , as an alternative to async , I rewritten the zero code and managed to get the query to the database done before, simply nesting the ( express ) and sending data (socket.io ) within the query function.

So the query is performed and then the page is sent to the client at the same time that the data obtained from the DB is sent by socket, updating the sent page.

    
27.08.2015 / 17:56