Search code examples
node.jsdesign-patternsevent-driven-design

Using the value from callback


I am developing application in Node.js with ExpressJS. I am new to event-driven development and I have a basic question about event-driven architecture and visibility.

I have a service which needs to make several MySQL queries and return them as one JSON object. Something like this:

exports.someService = function(..) {
  mysql.query("some select", function(rows...) {
   // here I want to store the rows in a way to be visible from parent function
  });

  mysql.query("some other select where id=some value from previous select", function(rows...) {
    res.send(rows from this query + rows from previous query)
  });  
}

How can I do this?


Solution

  • If you want to use the result of a callback you'll have to place the code that uses the result within the callback itself.

    So your example would become:

    exports.someService = function(..) {
       mysql.query("some select", function(rows...) {
    
          mysql.query("some other select where id=some value from previous select",
            function(rows...) {
             res.send(rows from this query + rows from previous query)
         });  
       });
    }
    

    You can clean it up by un-nesting your callbacks and passing them the relevant parameters:

    exports.someService = function(..) {
       mysql.query("some select", cb1);
    }
    
    function cb1(sql_result_1) {
         mysql.query("some other select where id=some value from previous select",
           function(sql_result2) { cb2(sql_result_1, sql_result2) });
    }
    
    function cb2(sql_result_1, sql_result2) {
        res.send(rows from this query + rows from previous query)
    }
    

    You have to chain your callbacks together because, in an event based model, code doesn't block.

    E.g.,

    mysql.query("...", some_cb);
    mysql.query("...", some_other_cb);
    

    some_cb and some_other_cb will, conceptually, be run at the same time. This is because Control passes through callbacks instead of in the normal line-by-line method which you are used to.