ParisNakitaKejser
ParisNakitaKejser

Reputation: 14839

MySQL problems in Node.js - fetch all query

I have a problem in Node.js i have build my own modul, to handle a kind of stuff, in this modul i have a function getList() where i can get a inputs to my config.

my source code is this:

var config = {
    'limit' : 0
};

var dict = [];


exports.getList = function(db, conf) {
    db.query("SELECT id, title FROM animal a " + (config.limit > 0 ? " LIMIT " + config.limit : "" ), function(err, rows, fields) {
        if(err) {
            console.log(err);
        }

        for(var key in rows) {
                var row = rows[key];
        //
                dict.push({
                    'title' : 'Buster',
                    'animal' : 'Dog',
                    'age' : '12',
                    'photo' : 'https://placeholdit.imgix.net/~text?txtsize=24&txt=260×200&w=260&h=200'
                });
    });

    console.log(dict);
    console.log(config);

    return dict;
}

The problem is when i start my application up and first time i call this script the dict its empty, second time its have 3 rows from my database, and every time i reload the pages its add 3 more to it.

i have trying to find out how i handle this issue whiteout a aware hope somebody can help me here, thanks a lot.

Upvotes: 3

Views: 927

Answers (2)

Sean
Sean

Reputation: 3042

you should pass the callback into the db.query, or return the promise instead of the dist, as db.query is an async method, you can not call an async method in sync way. In old days, we would use a callback, for example

exports.getList = function(db, conf, callback) {
   db.query('', function (err, result) {
     if(err) return callback(err);
     callback(null, result);
   });
}

getList(db,conf, function(err, result) {
  console.log(result);
});

now I would like to recommand use promise.

exports.getList = function(db, conf) {
    return new Promise(function(resolve, reject) {
      db.query("SELECT id, title FROM animal a " + (conf.limit > 0 ? " LIMIT " + conf.limit : "" ), function(err, rows, fields) {
          if(err) {
              reject(err);
              return;
          }
          var dict = [];
          for(var key in rows) {
                var row = rows[key];
        //
                dict.push({
                    'title' : 'Buster',
                    'animal' : 'Dog',
                    'age' : '12',
                    'photo' : 'https://placeholdit.imgix.net/~text?txtsize=24&txt=260×200&w=260&h=200'
                });
        });
        resolve(dict);
    });

}

getList(db,config).then(function(result) {
  console.log(result);
}).catch(function(e) {
  console.log(e);
});

and you can also call two query in parallal for example

Promise.all([getList1(db,config), getList2(db,config)]).then(function(result) {
  console.log('result of getList1', result[0]);
  console.log('result of getList2', result[1]);
});

and with promise, you can use es6 generator with co, to call async method in a sync manner

var co = require('co');

co(function* () {
  try {
     var result = yield getList(db, conf);
     // here is your result
  } catch(e) {
     console.log(e);
  }

});

Upvotes: 2

Nir Levy
Nir Levy

Reputation: 12953

You are initialiIng dict once, outside of the function. This call happens only once when you require this module.

Later on in the function you push the new rows to it- so it keeps adding ip, theres nothing that clears the array between calls.

You should move the initialization of dict to inside the function

EDIT: after seeing your comments, there is one more (bigger) issue here: you are ignoring the asynchronous nature of node.js.

Node works asynchronously, which means it will run db.query, your both console.log, and the return statement one after the other without waiting for the prior to end. this means that the return statement can be executed before db.query and it's callback (will probably will, as connecting db is slower operation than the two console logs).

so when you are not initializing dict - you will get every time the results that were inserted to it on the previous call of the function. once you are clearing it, you are getting it empty, as it has not filled yet.

The solution should be not to return the result like that, but build your function to except a callback, and return in this callback the result (this way you can control when this callback is called, and run it only once you have the results)

This is how I'd do it:

exports.getList = function(db, conf, callback) {
    var dict = [];
    db.query("SELECT id, title FROM animal a " + (config.limit > 0 ? " LIMIT " + config.limit : "" ), function(err, rows, fields) {
        if(err) {
            console.log(err);
        }

        for(var key in rows) {
                var row = rows[key];
        //
                dict.push({
                    'title' : 'Buster',
                    'animal' : 'Dog',
                    'age' : '12',
                    'photo' : 'https://placeholdit.imgix.net/~text?txtsize=24&txt=260×200&w=260&h=200'
                });
        console.log(dict);
        console.log(config);
        callback(dict); // this will return the results to the calling function's callback
    });

}

Upvotes: 2

Related Questions