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();
})
})();
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.
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();
}