【问题标题】:How to avoid/prevent infinite recursive call in Node.js?如何避免/防止 Node.js 中的无限递归调用?
【发布时间】:2017-03-10 22:52:00
【问题描述】:

我的Node.js 应用程序中有一个javascript 函数,它调用自身以在MongoDB 的父子层次结构中查找其级别。文档将尝试查找其父级,如果找到则会增加级别并继续直到找不到父级。如下所示,

function findLevel(doc, level, callback){
    if(!doc)
        return callback(null, level);
    var query = {
        id: doc.parentID
    };
    model.findOne(query, function(err, parentDoc){
        if(err){
            return callback(err, level)
        };
        return findLevel(parentDoc, level+1, callback);
    })
}

这很有可能产生无限递归调用。其中一种情况是 parentID 与当前文档的 id 相同。这可以通过在查找查询中包含另一个条件来避免,但我仍然担心我可能会错过一些东西,它可能导致整个应用程序崩溃/终止。在Node.js 中是否有推荐的方法来避免/防止这种情况?或者我们可以限制递归调用的级别并优雅地停止它,就像说递归调用应该只进行到 n 级别?

【问题讨论】:

  • 当返回的父文档 id 与查询 id 相同时,这就是你停止的地方,对吧?
  • 如果您真的只关心顶级父级,为什么不在保存文档时使用顶级父级的 ID 保存它。或者在某个时间运行批处理作业来进行路径压缩。
  • @Sikorski 没有。在完美的场景中,我们会在找不到父对象时停止。
  • 当然,是的,一个请求会挂起 :-)(获取其中的许多最终会耗尽资源)。限制level 或保留访问过的图节点的历史绝对是一个好主意。或者一开始就不构建圆形图。
  • 另一种方法是收集您见过的所有 ID,并在您的递归将您带到您以前见过的 ID 时停止并停止。

标签: javascript node.js mongodb recursion


【解决方案1】:

您可以通过记下您在递归期间遇到的所有 ID 并在之前处理过 ID 时立即停止来实现循环检测。

function findLevel(doc, callback) {
    var level = 0, seen = {};

    (function getParent(doc) {
        // proper termination
        if(!doc || !doc.parentID) return callback(null, level);

        // cycle detection
        if (seen.hasOwnProperty(doc.parentID)) return callback(new Error("cycle detected"));
        seen[doc.parentID] = true;

        // recursion
        model.findOne({id: doc.parentID}, function (err, parentDoc) {
            if (err) return callback(err);

            level++;
            getParent(parentDoc);
        });
    })(doc);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 2013-05-25
    相关资源
    最近更新 更多