如何在节点 js 中执行此异步功能

Posted

技术标签:

【中文标题】如何在节点 js 中执行此异步功能【英文标题】:How can I do this asyn feature in nodejs 【发布时间】:2012-11-18 20:11:23 【问题描述】:

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

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;

【问题讨论】:

【参考方案1】:

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

这也是不可能的,结果永远不变(null)

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

在 calc() 函数中放置一个回调作为第二个参数,并在 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);
   );

现在,如果您希望 main 返回该结果,您还必须在 main 中放置一个回调参数并像以前一样调用该函数。

我建议您查看 async 它是一个很棒的图书馆,不必处理这种麻烦

【讨论】:

【参考方案2】:

这是一种非常粗略的方法,通过使用事件来实现循环以执行计算(模拟异步数据库调用)。

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

【讨论】:

以上是关于如何在节点 js 中执行此异步功能的主要内容,如果未能解决你的问题,请参考以下文章

如何在节点 js 中正确使用等待/异步与 for 循环

如何运行多个异步函数然后执行回调?

如何使用 Q.js 在循环中执行异步函数

高分请教,js的DOMNodeRemoved事件如何在删除节点之后才执行这个事件呢

Node Js:如何在服务器启动时异步执行函数

我如何在 discord js 中使用异步功能来制作问题游戏?