catch mysql errors before sending HTTP response

只谈情不闲聊 提交于 2019-12-11 08:33:23

问题


I am coming from php background where sql queries are blocking.

My usual setup is to make a try, catch block to handle any possible errors that might happen during table updating. I wanted to transfer this logic to nodejs, but it's asynchronous nature is making this troublesome. Take a look at example code:

var httpServer = Https.createServer(httpsOptions, function (request, response) {


try {
     //many queries in if-else, switch statements
     if(something){
     mysqlConnection.query(query,[],function(err, result){});
     }else{
     //many queries will follow
       if(somethingelse){
        mysqlConnection.query(query2,[],function(err, result){});
       }else{
        mysqlConnection.query(query3,[],function(err, result){});
          if(andsoon){}
       }
     }

     response.writeHead(200, { "Content-Type": "text/plain" });
     response.end("Got it.");
     console.log("Response successful");
}catch(error){
     console.error(error);
     response.writeHead(400, { "Content-Type": "text/plain" });
     response.end("Error.");
}

}).listen(8000);

So, response.end() will trigger before the query executes so I send the message before I know if the query was successful. I could wrap the response.end() code in callback, but there are MANY queries that are executing, so now I have to track how many were executed so far. Things get worse, 1 if-else control flow requires just 1 query, some other requires 10 so there is crazy overhead with tracking when the code is completed.

This all can't be the optimal workflow. What do you do when you have a complex query system and you want to send response only after all queries have executed(or failed)?


回答1:


You've put null callbacks from your .query invocations. That's your problem.

mysqlConnection.query(query,[],function(err, result){});
                               xxxxxxxxxxxxxxxxxxxxxxxx

Javascript goes on to run the next statement after the one shown immediately without waiting for the query to finish. You know the query is complete (or it hit an error) only when the .query method invokes your callback function.

So, you need to do something like this instead.

mysqlConnection.query(query,[],function(err, result){
    if (err) throw Error(err);
    //many queries will follow
    if(somethingelse){
           ...
    }
});

A sequence of queries like you need ends up with an absurdly deeply nested set of callback functions. But don't despair: Javascript's Promise pattern works around this for you and gives you clean code. Use npm's promise-mysql package. And write code like this.

    mysqlConnection.query(query,[])
    .then (function(mySqlConnection) {
         if (somethingelse) 
             return mysqlConnection.query(query2,[]) 
         else
             return mysqlConnection.query(query3,[]) 
         })
     .then (function(mySqlConnection) {
          return mysqlConnection.query(query4,[]) 
         })
     .then (function(mySqlConnection) {
          response.writeHead(200, { "Content-Type": "text/plain" });
          response.end("Got it.");
         })
     .catch (function(err)) {
          /* failure somewhere ! */
         });

You have a series of then functions, with a catch at the end. The Promise subsystem hides all the callback invocation for you, organizing it this way instead. (Notice that I did not debug this sample code.)

You must figure out this Promise stuff to program sql / nodejs successfully. It's counterintuitive at first (at least it was for me when I was learning it). But it's worth your effort. Pro tip: if you're stepping through this kind of code in a debugger, use Step Into liberally.



来源:https://stackoverflow.com/questions/54346143/catch-mysql-errors-before-sending-http-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!