2014-12-06 45 views
2

最后,stackoverflow上报告了实际的堆栈溢出错误!RangeError:调用堆栈超出异步.eachSeries

我得到以下错误在下面的代码:

var m = pathA.substr(-(pathB.length)); // var 
              ^
RangeError: Maximum call stack size exceeded 

我相当肯定的答案就在这里报道,朝下方:

https://github.com/caolan/async/issues/75

不过,我不不明白如何解决我的代码。就我所知,我不是在异步函数内调用同步函数。任何人都可以澄清我需要做些什么来修复我的代码?

我在遍历结果集的交叉积来连接路径字符串,其中一个是另一个的子字符串。

var i = 0; 
    async.eachSeries(results.rows, function (r, next2a) { 
     var pathA = results.rows[i].id_path; 
     var j = 0; 
     async.eachSeries(results.rows, function (r2, next1a) { 
      var pathB = results.rows[j].id_path; 
      //check i=j 
      if (!(i == j)) { 
       var m = pathA.substr(-(pathB.length)); // var m = (pathA || '').substr(-((pathB) ? pathB.length : 0)); 
       if ((m == pathB) && (pathA.length > pathB.length)) { 
        logger.log('DEBUG', (pathB + ' => ' + pathA)); 
        conn.query("UPDATE user_token_details SET id_l1=$1, id_l2=$2, id_l3=$3, id_l4=$4,id_l5=$5,id_path2=$9, id_path=$6 WHERE token_uuid=$7 AND user_uuid=$8", 
         [results.rows[i].id_l1, results.rows[i].id_l2, results.rows[i].id_l3, results.rows[i].id_l4, results.rows[i].id_l5, results.rows[i].id_path, 
          results.rows[j].token_uuid, user_uuid, results.rows[j].id_path], 
         function (error, result) { 
          if (error) { 
           throw error; 
          } 
          j++; 
          next1a(); 

         }) 
       } else { 
        j++; 
        next1a(); 
       } 
      } else { 
       j++; 
       next1a(); 
      } 


     }, function() { 
      i++; 
      next2a(); 
     }); 


    }, function (err) { 
}); 

下面是这个意大利面条的形式:

var A = [0, 1, 2, 3, 4...300]; 
async.eachSeries(A, function (a, next_a) { 

    async.eachSeries(A, function (b, next_b) { 
     // "Range Error: Maximum call stack size exceeded" 
     doSomethingAsync(a,b, function() { 
     next_a(); 
     }); 

    }, function (err) { 
     next_b(); 
    }) 

}, function (err) { 
    // resume 
}) 
+1

哇,我认为自己非常好与异步,但没有办法在地狱,我会去尝试找出那个代码。尝试把它归结为一些更人性可分析的东西,或者我怀疑你会在这里得到0个答案 – mkoryak 2014-12-06 02:04:45

+0

它与这个问题有关:https://github.com/rdegges/node-lupus http://www.rdegges.com/for-loops-in-node/ – metalaureate 2014-12-06 02:30:21

+0

@mkoryak我添加了第二个示例 – metalaureate 2014-12-06 02:44:23

回答

5

的问题是,如果里面的回调异步调用的是async.eachSeries仅表现异步。在你的情况下,你最近的两次调用next1a没有执行查询,所以它们同步发生,从而扩展了调用栈。在这种情况下,您可能会迭代到足以达到最大堆栈深度。最简单的方法是始终以异步方式调用next1a

setImmediate(next1a); 

更换的

next1a(); 

每个实例,除了一个是因为查询已经异步。请注意,虽然process.nextTick(next1a)也可以工作,但它有可能阻止事件循环处理任何其他任务。这是因为process.nextTick将回调排队为microtask,而setImmediate将回调排队为macrotask

+0

完全真棒感谢您的解答和解释。 – metalaureate 2014-12-06 03:14:54

+0

我很好奇,如果这能解决它。当我用nextTick进行实验时,发现它像一个同步函数调用一样工作(节点v0.10.29) – Andras 2014-12-06 03:30:29

+0

它会。 'nextTick'在当前执行流程之外触发一个回调,所以堆栈在执行之前将被解除。 – loganfsmyth 2014-12-06 04:10:23

相关问题