Reputation: 5246
Edit
Upon closer inspection, it would appear that async.forEach
finishes before getCurrencies
is even run the first time... How do I resolve this? I thought returning a promise would essentially 'chain' these promises together?
I have the below code, which attempts to read transactions from mysql. Due to the size of the table and the length of time query takes, I'm breaking it up and using promises to populate an object. However, getCurrencies
doesn't update the model's currencyCode
- Yet, both console.log
report correct values. Can someone explain what I'm doing wrong please? I'm quite new to promises still. Thanks.
main object building
connection.query(query).then(function(items) {
async.forEach(items, function(element) {
element.ptype = 'merchants';
element.type = 'transactions';
element.currencyCode = null;
getCurrencies(element.currencies_id).then(function(result) {
console.log(result.currencyCode);
element.currencyCode = result.currencyCode;
console.log(JSON.stringify(element));
});
});
res.send(items);
});
getCurrencies
function getCurrencies(transactionId) {
var currencies_query = '';
currencies_query += 'SELECT ';
currencies_query += 'iso_code AS currencyCode, ';
currencies_query += 'name AS `currencyName`, ';
currencies_query += 'symbol AS `currencySymbol`, ';
currencies_query += 'exponent AS `currencyExponent`, ';
currencies_query += 'iso_num AS `currencyNumber` ';
currencies_query += 'FROM ';
currencies_query += 'currencies ';
currencies_query += 'WHERE ';
currencies_query += 'id = ' + transactionId;
return new Promise(function(resolve, reject) {
connection.query(currencies_query).then(function(rows) {
resolve(rows[0]);
});
});
};
And output from both console.log
s
first
GBP
second
{"id":11213595,"pid":100856,"uri":"/rest/transactions/11213595","puri":"/rest/merchants/100856","path":"/resellers/1/customers/5/merchants/100856/transactions/11213595","transactionID":11213595,"currencies_id":1,"transactionUri":"/rest/transactions/11213595","ptype":"merchants","type":"transactions","currencyCode":"GBP"}
resulting api response from postman
{
"id": 11213615,
"pid": 103845,
"uri": "/rest/transactions/11213615",
"puri": "/rest/merchants/103845",
"path": "/resellers/1/customers/2368/merchants/103845/transactions/11213615",
"transactionID": 11213615,
"currencies_id": 1,
"transactionUri": "/rest/transactions/11213615",
"ptype": "merchants",
"type": "transactions",
"currencyCode": null
}
As you can see, currencyCode
is still null
- Why?! :(
Upvotes: 0
Views: 56
Reputation: 1345
As you can see, currencyCode is still null - Why?! :(
I didn't work with "async.forEach" before but I think, that currencyCode is Null - because you call promise "getCurrencies", whith work asynchronously
If you need to respond to client with result of work few promises - you have to collect promises to array, and then call Promise.all (which will return array of results of all promises)
And you should send response in next block of chain. I think it should work
connection.query(query)
.then(function(items) {
var arPromises = [];
async.forEach(items, function(element) {
element.ptype = 'merchants';
element.type = 'transactions';
element.currencyCode = null;
arPromises.push(
new Promise(function (resolve, reject) {
getCurrencies(element.currencies_id)
.then(function(result) {
element.currencyCode = result.currencyCode;
resolve(element);
}).catch(function (error) {
//do something with error
if(error)
reject(error);
});
})
);
});
return Promise.all(arPromises);
}).then(function(items){
res.send(items);
}).catch(function (error) {
if(error)
console.log(error);
});
And my advice, finish chain with "catch" block - for avoid lost errors
Upvotes: 1