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、リクエストが終了したことが lib に通知されます。それらがすべて終了するasyncと、 への呼び出しで 2 番目の引数として指定したコールバック クロージャーを呼び出します。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 に答える