Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何将嵌套for循环转换为递归?_Javascript_Node.js - Fatal编程技术网

Javascript 如何将嵌套for循环转换为递归?

Javascript 如何将嵌套for循环转换为递归?,javascript,node.js,Javascript,Node.js,我从Memcached中获取了一些数据,但我完全无法理解nodejs的异步性。 我想把所有结果放到一个对象中 这是我通常会做的: for( x = startX; x <= endX; x++ ) { for( y = startY; y <= endY; y++ ) { oData[ x + '_' + y ] = Db.get( x + '_' + y ); } } 这不是一个递归问题,而是一个“异步问题”。您的问题是NodeJ异步访问memcached,

我从Memcached中获取了一些数据,但我完全无法理解nodejs的异步性。 我想把所有结果放到一个对象中

这是我通常会做的:

for( x = startX; x <= endX; x++ )
{
  for( y = startY; y <= endY; y++ )
  {
    oData[ x + '_' + y ] = Db.get( x + '_' + y );
  } 
}

这不是一个递归问题,而是一个“异步问题”。您的问题是NodeJ异步访问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);
    }
}
这段代码实际上是在创建一个函数数组,每个函数调用特定键的
Db.get
方法,并将结果添加到
oData
变量中

创建函数数组后,我们使用
async
库的
parallel
方法,该方法获取函数数组并并行调用它们。这意味着您的代码将向memcached发送一系列请求,以便一次获取您的数据。当每个函数完成时,它调用
回调
函数,该函数告诉
异步
库请求已完成。当所有这些都完成时,
async
调用回调闭包,该闭包是您作为
parallel
方法调用中的第二个参数提供的。调用该方法时,您可能知道A.出现了问题,需要从中恢复错误,或者B.所有请求都已完成,您可能拥有或可能没有所请求的所有数据(请求的密钥已过期或过时,或者其他)。从那里,你可以做任何你想做的事,知道你已经完成了所有你需要的钥匙

我希望这能有所帮助。

并行获取:

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);         
       });
    } 
  }
}
功能加载点(cb)
{
var-oData={};

对于(x=startX;x)在您的第一个代码中,您一次将所有Memcached请求排队,然后获取结果,而不是一次将它们序列化。这可能是大量排队的请求。这是故意的吗?@Alnitak在这两个代码段中,我将所有请求排队并触发它们(几乎)立即。这是故意的,因为它是最接近OP代码的版本。当然有更好的方法来处理它,使其更高效,例如,MemcacheD允许您通过单个请求对大量密钥执行多重获取。这种方法更适合这里,对大量密钥更快/更高效关键点。我只是选择尽可能让答案接近OP的当前流程-这样他就可以很容易地理解(hoepfully)我明白了,谢谢。问题是:在
data[key]=result;
关键点总是最后一个关键点,似乎有一个参考问题,我的“自制”也有这个问题想法:\n也许我应该使用memcached而不是memcache插件,因为它支持multiget:)我做了一个修复;它会工作的-但是有比使用那样的闭包更理想的方法来处理这个问题。是的,你们都是对的带有multiget的模块工作得更好。无论如何,谢谢:)
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
});
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);
}