Reputation: 148
I have a code to do some calculation. How can I write this code in an asyn way? When query the database, seems we can not get the results synchronously. So how to implement this kind of feature?
function main () {
var v = 0, k;
for (k in obj)
v += calc(obj[k].formula)
return v;
}
function calc (formula) {
var result = 0;
if (formula.type === 'SQL') {
var someSql = "select value from x = y"; // this SQL related to the formula;
client.query(someSql, function (err, rows) {
console.log(rows[0].value);
// *How can I get the value here?*
});
result = ? // *How can I return this value to the main function?*
}
else
result = formulaCalc(formula); // some other asyn code
return result;
}
Upvotes: 3
Views: 81
Reputation: 340
Its not possible to return the result of an asynchronous function, it will just return in its own function scope.
Also this is not possible, the result will always be unchanged (null)
client.query(someSql, function (err, rows) {
result = rows[0].value;
});
return result;
Put a callback in the calc() function as second parameter and call that function in the client.query callback with the result
function main() {
calc(formula,function(rows) {
console.log(rows) // this is the result
});
}
function calc(formula,callback) {
client.query(query,function(err,rows) {
callback(rows);
});
}
Now if you want the main to return that result, you also have to put a callback parameter in the main and call that function like before.
I advice you to check out async its a great library to not have to deal with this kind of hassle
Upvotes: 3
Reputation: 26700
Here is a very crude way of implementing a loop to perform a calculation (emulating an asynchronous database call) by using events.
As Brmm alluded, once you go async you have to go async all the way. The code below is just a sample for you to get an idea of what the process in theory should look like. There are several libraries that make handling the sync process for asynch calls much cleaner that you would want to look into as well:
var events = require('events');
var eventEmitter = new events.EventEmitter();
var total = 0;
var count = 0;
var keys = [];
// Loop through the items
calculatePrice = function(keys) {
for (var i = 0; i < keys.length; i++) {
key = keys[i];
eventEmitter.emit('getPriceFromDb', {key: key, count: keys.length});
};
}
// Get the price for a single item (from a DB or whatever)
getPriceFromDb = function(data) {
console.log('fetching price for item: ' + data.key);
// mimic an async db call
setTimeout( function() {
price = data.key * 10;
eventEmitter.emit('aggregatePrice', {key: data.key, price: price, count: data.count});
}, 500);
}
// Agregate the price and figures out if we are done
aggregatePrice = function(data) {
count++;
total += data.price;
console.log('price $' + price + ' total so far $' + total);
var areWeDone = (count == data.count);
if (areWeDone) {
eventEmitter.emit('done', {key: data.key, total: total});
}
}
// We are done.
displayTotal = function(data) {
console.log('total $ ' + data.total);
}
// Wire up the events
eventEmitter.on('getPriceFromDb', getPriceFromDb);
eventEmitter.on('aggregatePrice', aggregatePrice);
eventEmitter.on('done', displayTotal);
// Kick of the calculate process over an array of keys
keys = [1, 2, 3]
calculatePrice(keys);
Upvotes: 0