2012-11-30 30 views
3

我有一段代码来进行一些计算。 如何以异步方式编写此代码? 查询数据库时,似乎无法同步获得结果。 那么如何实现这种功能呢?如何在nodejs中执行此异步功能

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; 
} 

回答

3

它不可能返回异步函数的结果,它只会返回它自己的函数范围。

而且这是不可能的,结果永远是不变的(空)

client.query(someSql, function (err, rows) { 
    result = rows[0].value; 
}); 
return result; 

放入钙()函数,第二个参数的回调,并调用该函数与该client.query回调导致

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

现在如果你想主要以返回结果,你也必须把回调参数在主里面并调用它像以前一样。

我建议你检查出async它的一个伟大的图书馆不具备处理这种麻烦

0

这里是实现一个循环来进行计算(模拟异步数据库调用)的一种非常原始的方式通过使用事件。由于Brmm暗示,一旦你走异步,你必须一路走向异步。下面的代码只是一个示例,让您了解理论上的过程应该是什么样子。有几个库可以处理异步呼叫的同步过程,并且您还希望查看以下内容:

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);