Node.js mysql results to array

Jon Quiros SV picture Jon Quiros SV · Sep 10, 2018 · Viewed 7.7k times · Source

I've been slowly learning node.js so that I can integrate things better between a lot of our current ops (mysql) and Xero accounting.

I have several tables in mysql, one each for ["invoices","accounts","items","organisations","receipts","taxRates","users","trackingCategories"] and each of those tables has a JSON column with the same name as the table it's in. This is NOT a json question.

Sending a query like ""select "+ wewant1[i] + " from "+wewant1[i]" is basically simple "select invoices from invoices" and easy to iterate through.

I can get the mysql results to list, but need to get each separate "list" as an array of results.

I would ultimately like to be able to reference the results from "select invoices from invoices" as an "invoices" array in node (invoices[0], invoices[1], etc).

I've tried avoiding "callback hell" and still cannot get this to work... Any tips are very welcome!

Here is the current code:


20180910 22:00 GMT-6 Thanks Steven! I think I got it with this:

const XeroClient = require('xero-node').AccountingAPIClient;
const XeroErrors = require('xero-node').XeroError;
var mysql = require('mysql');

const config = {
    appType: "private",
    consumerKey: "_____",
    consumerSecret: "_____",
    privateKeyPath: "../../../ssl/_____.pem"
  };

var con = mysql.createConnection({
    host: "_____",
    user: "_____",
    password: "_____",
    database: "xeroetc"
});


(async function(){

let wewant1 = ["invoices","accounts","items","organisations","receipts","taxRates","users","trackingCategories"];

let xero = new XeroClient(config);

function getmydata(it, callback) {
       var sql = "select "+it+" from "+it;
       con.query(sql, function (err, result, fields) {
        if (err) throw err;
        callback(null,result);
    });
  };
  
  const promises = wewant1.map(it => {
     return new Promise((resolve, reject) => {
       getmydata(it, function querydata(err, result) {
         if (err) {
           reject(err);
         } else {
           resolve(result);
         }
       });
     })
  });

  Promise.all(promises)
  .then(results => {
    //results is a array of the resolved promises
    invoices=results[0];
    accounts=results[1];
    items=results[2];
    organisations=results[3];
    receipts=results[4];
    taxRates=results[5];
    users=results[6];
    trackingCategories=results[7];
    console.log(invoices);
    })
  .catch(err => {})
    .then(() => {
        con.end();
    })
})();

Answer

Steven Spungin picture Steven Spungin · Sep 10, 2018

Map your array to promises, and then use Promise.all. This also solves your unstated problem of closing your connection too early.

var mysql = require('mysql');

var con = mysql.createConnection({
  host: "10.0.1.103",
  user: "badayaba",
  password: "yadabuba",
  database: "xeroetc"
});




let wewant1 = ["invoices", "accounts", "items", "organisations", "receipts", "taxRates", "users", "trackingCategories"];

function getmydata(sql, result, callback) {
  var query = con.query(sql);
  query.on('result', function(row) {
    callback(null, row);
  });
};

const promises = weweant1.map(it => {
  return new Promise((resolve, reject) => {
    getmydata(sql, it, function querydata(err, result) {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  })
});

Promise.all(promises)
  .then(results => {
    //results is a array of the resolved promises
  })
  .catch(err => {})
  .then(() => {
    // then after catch is a finally block
    con.end();
  })

Of course you can also use async/await and get rid of the then nesting. You can additionally promisify getmydata. All use the same principle though: Wait on an array of promises.

Using async/await

If getmydata returned a promise or was declared async, the following snippet would do, assuming it was in an async function. So much cleaner...

const promises = weweant1.map(it => getmydata(sql, it))

try {
  const results = await Promise.all(promises)
} catch (e) {
  // handle error
} finally {
  con.end();
}