3

計算を行うためのコードがあります。このコードをasynの方法で書くにはどうすればよいですか?データベースにクエリを実行すると、結果を同期的に取得できないようです。では、この種の機能を実装するにはどうすればよいでしょうか。

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

2 に答える 2

3

非同期関数の結果を返すことはできません。独自の関数スコープで返されるだけです。

また、これは不可能です。結果は常に変更されません (null)

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

コールバックを calc() 関数に 2 番目のパラメーターとして配置し、その関数を 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の優れたライブラリをチェックすることをお勧めします

于 2012-11-30T16:15:47.010 に答える
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);
于 2012-11-30T16:34:14.623 に答える