【问题标题】:Async and recursion in nodejsnodejs中的异步和递归
【发布时间】:2013-07-11 10:08:42
【问题描述】:

expressmongoose 开始,我经常需要对集合进行一些批处理操作。 然而,它通常涉及回调,考虑到 nodejs 中的并发性是如何编码的,这很痛苦。 所以基本上

//given a collection C 
var i = 0;
var doRecursive = function(i){
    if(i<C.length){
      C[i].callAsync(err,result){
        i=+1;
        return doRecursive(i);
       }
    }else{
      return done();
    }
}
doRecursive(i);

现在我不记得在使用 node 获得 stackover 流之前的最大堆栈是多少,但我猜有 10 000 个元素,它不会这样做。 我想知道是否有其他方法可以处理这个问题,如果是,它们是什么? 谢谢

【问题讨论】:

  • 嗯,异步函数将有助于堆栈溢出,因为回调将位于不同的调用堆栈中。但是,通过分解成不同的堆栈,它会使return 变得毫无用处。
  • 看看async

标签: javascript node.js mongodb express mongoose


【解决方案1】:

我认为您可以简单地进行自我迭代而不是真正的递归,因为您没有钻入深层对象:

function doRecursive (C, i){
    i=i||0;
    if(i<C.length){
       C[i].callAsync(err, function(result){
          doRecursive(C, ++i);
       });
    }else{
       done();
    }
};

doRecursive(C);

如果代码按标签运行,则不会创建高堆栈。 我对 C 进行了本地化,以便它执行得更快,并且可能在其他集合上重用。 该模式还可以轻松地将其推迟到长时间运行的操作中,只需更改

doRecursive(C, ++i);

setTimeout( doRecursive.bind(this, C, ++i), 50 );

【讨论】:

    【解决方案2】:

    如果目标是异步迭代集合,则有许多可用的控制流库。

    一个很好的例子是async 和它的reduce function

    async.reduce(C, 0, function (memo, item, callback) {
        item.callAsync(function (err, result) {
            if (err) {
                callback(err);
            } else {
                callback(null, memo + result);
            }
        });
    }, function (err, result) {
        // ...
    });
    

    注意:目前尚不完全清楚您想从doRecursion 获得什么值,因此这里仅以加法为例。

    【讨论】:

    • 我知道异步。 async 有没有办法概括递归,所以递归可以用“更漂亮”的方式编写?人们告诉我递归和异步调用不应该存在stackoverflow问题,我需要对其进行测试以确定。编辑:我看到你正在使用 Async.reduce ,很有趣,不知道那个。
    猜你喜欢
    • 2015-10-30
    • 2014-05-21
    • 2015-03-14
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 2016-03-05
    • 2017-05-21
    • 1970-01-01
    相关资源
    最近更新 更多