2

Let's say I have an Express app and I want to display something I get from a database. I have a file that contains this (using node-mysql for database interaction)

exports.getData = function() {                                                                   
  connection.query('SELECT * FROM table', function (error, rows, fields) {                                                                                    
    return rows[0];                                                                               
  });                                                                                                                                                                       
}

I'd love to be able to call that and have the data to pass on to the template language. However, it doesn't work that way, because (I think) the call back doesn't return until after the function has exited, resulting in getData returning undefined.

I must be missing some important "aha" moment about callbacks. If I want to interact with the database, am I forced to do all the logic in routes/index.js (the controller for the page I'm serving) and finally render the page at the bottom of a series of callbacks?

4 Answers 4

3

Pass in a callback as an argument to getData() that is exported...

exports.getData = function(callback) {                                                                   
  connection.query('SELECT * FROM table', function (error, rows, fields) {                                                                                    
    callback(error, rows[0]);                                                                               
  });                                                                                                                                                                       
}

Then, you can do...

var data = require("data");
data.getData(function(error, firstRow) {  });

Tadman made a good suggestion of following the convention that the first argument is for the error. Doing it this way, we can propagate the error information.

Sign up to request clarification or add additional context in comments.

2 Comments

You may want to follow the NodeJS convention of defining callback as f(error, rows) instead of just f(rows), otherwise any error here is ignored and lost.
@John Feeling dumb is an important time in any programmer's life, as it usually means that they learned something new. I try to feel dumb (and mostly succeed) every day :)
0

Something like this is probably what you are looking for. Call another function in your query callback.

exports.getData = function() {                                                                   
  connection.query('SELECT * FROM table', function (error, rows, fields) {                                                                                    
    renderPage(rows[0]);                                                                               
  });                                                                                                                                                                       
}

function renderPage(data) {
    app.render('page', {
        "data": data
    }
}

Comments

0

You can use "promise" in this link can to find more information

Promises provide a compelling alternative to raw callbacks when dealing with asynchronous code. Unfortunately, promises can be confusing and perhaps you’ve written them off. However, significant work has been done to bring out the essential beauty of promises in a way that is interoperable and verifiable. The result is Promises/A+, a specification that is making its way into promise libraries and even the DOM.

var promise = (connection.query('SELECT * FROM table')
promise.then(function (somedata){renderPage(rows[0])};)

Comments

0

you may want to check out the async module: https://github.com/caolan/async

Here is an example where I make a few data calls in parallel before rendering the view.

var async = require('async'),
    example = require('example-api-client');

module.exports = function(app){

    app.get('/example', function(req, res){

        async.parallel(
            {
                apples: function(cb){
                    example.getData('apples', cb);
                },
                oranges: function(cb){
                    example.getData('oranges', cb);
                }
            },
            function(err, results){
                //TODO: handle errors
                res.render('example', results);
            }
        );

    });

};

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.