0

我从 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);
4

2 回答 2

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库请求已完成。当所有这些都完成后,async调用您在调用中作为第二个参数提供的回调闭包parallel方法。调用该方法时,您要么知道 A. 出了点问题,并且您有错误要从中恢复,要么 B. 所有请求都已完成,您可能拥有或不拥有您请求的所有数据(请求的过期或过时的密钥, 管他呢)。从那里,你可以做任何你想做的事,知道你已经完成了所有你需要的钥匙的要求。

我希望这有帮助。

于 2012-05-15T22:51:33.560 回答
0

并行获取:

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);
}
于 2012-05-16T05:56:26.083 回答