如何在节点 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 中执行此异步功能的主要内容,如果未能解决你的问题,请参考以下文章