我从Memcached获取了一些数据,但nodejs的异步完全让我失望。 我想把所有结果都放到一个对象中。
这就是我通常会做的事情:
for( x = startX; x <= endX; x++ )
{
for( y = startY; y <= endY; y++ )
{
oData[ x + '_' + y ] = Db.get( x + '_' + y );
}
}
但我无法弄清楚如何
Db.get()
函数需要密钥和回调(function(error, result) {}
)
这只会增加x ...
var onGet = function (error, result)
{
x++;
if(!error && result !== null)
{
oData[ x + '_' + y ] = result
}
};
Db.get(x + '_' + y, onGet);
答案 0 :(得分:2)
这不是递归问题,而是“异步问题”。您的问题是NodeJS异步访问memcached而您的过程样式代码没有。所以,你需要以不同的方式思考问题。
function getMemcacheData(key, data)
{
DB.get(key, function(err, result)
{
if (err) return false;
data[ key ] = result;
})
}
var oData = {};
for (var x = startX; x <= endX; x++)
{
for (var y = startY; y <= endY; y++)
{
var key = x + "_" + y;
getMemcacheData(key, oData);
}
}
那会有效,但是 - 你还有另一个问题。您无法知道何时将MemcacheD数据加载到oData
,您只需等待并猜测即可。有办法解决这个问题;但我最喜欢的方法是使用名为async
的库。
使用异步,您可以这样做:
var syncStack = [],
oData = {};
for (var x = startX; x <= endX; x++)
{
for (var y = startY; y <= endY; y++)
{
(function(key)
{
syncStack.push(function(callback)
{
DB.get(key, function(err, result)
{
/** If you don't care about data not being loaded
you do this: */
if (!err)
{
data[ key ] = result;
}
callback();
/** If you do care, and you need to terminate if
you don't get all your data, do this: */
if (err)
{
callback(err);
return false;
}
data[ key ] = result;
callback();
})
});
})(x + "_" + y);
}
}
async.parallel(syncStack, function(error)
{
//this is where you know that all of your memcached keys have been fetched.
//do whatever you want here.
//if you chose to use the 2nd method in the fetch call, which does
//"callback(error)" error here will be whatever you passed as that
//err argument
});
这段代码实际上在做的是创建一个函数数组,每个函数都调用特定键的Db.get
方法,并将结果添加到oData
变量。
在创建函数数组之后,我们使用async
库的parallel
方法,该方法接受一系列函数并将它们全部并行调用。这意味着您的代码会将一堆请求发送到memcached以获取您的数据。每个函数完成后,它会调用callback
函数,该函数告诉async
lib请求已完成。完成所有这些操作后,async
将调用您提供的回调闭包作为parallel
方法调用中的第二个参数。当调用该方法时,您要么知道A.出错了,并且您有错误要从中恢复或B.所有请求都已完成,您可能拥有或未拥有您请求的所有数据(已过期或请求过期密钥) , 管他呢)。从那里,你可以随心所欲,知道你已经完成了所需的所有钥匙。
我希望这会有所帮助。
答案 1 :(得分:0)
parallel get:
function loadPoints(cb)
{
var oData = {};
for( x = startX; x <= endX; x++ )
{
for( y = startY; y <= endY; y++ )
{
var key = x + '_' + y;
num_points++;
Db.get(key, function(err, val) {
if (err)
return cb(err);
oData[key] = val;
num_points--;
if (num_points === 0)
cb(null, oData);
});
}
}
}
顺序获取:
function loadPoints(cb)
{
var oData = {};
function loadPoint(x, y)
{
var key = x + '_' + y;
Db.get(key, function(err, val) {
if (err)
return cb(err);
oData[key] = val;
if (x + 1 < endX)
return loadPoint(x + 1, y);
else if (y + 1 < endY)
return loadPoint(startX, y+1);
else
cb(null, oData);
});
}
loadPoint(startX, startY);
}