非法中断语句(Node.js)

aly*_*lyx 9 javascript asynchronous while-loop mongodb node.js

尝试在Node.js和MongoDB中查找唯一ID,方法是创建一个while循环,在MongoDB中查询现有ID,直到找到唯一值.如果ID已在使用中,则数字会在末尾递增,直到Mongo不返回任何内容.

一切正常,除了break;找到唯一ID 的声明.Node.js返回:SyntaxError: Illegal break statement

代码:

db.collection('landmarks').findOne({'id':uniqueIDer}, function(err, data){
    //if ID exists already
    if (data.id){

        var uniqueNumber = 1;

         while (1) {

            var uniqueNum_string = uniqueNumber.toString(); 
            var newUnique = data.id + uniqueNum_string;
            db.collection('landmarks').findOne({'id':newUnique}, function(err, data){

                if (data.id){
                    uniqueNumber++;
                }

                else {
                    saveLandmark(newUnique);
                    break;
                }
            });
        }
    }

    else {
        saveLandmark(uniqueIDer);
    }

});
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

编辑:

这是使用异步的固定代码,如果有人需要它:)

        db.collection('landmarks').findOne({'id':uniqueIDer}, function(err, data){

            if (data){
                var uniqueNumber = 1;
                var newUnique;

                async.forever(function (next) {
                  var uniqueNum_string = uniqueNumber.toString(); 
                  newUnique = data.id + uniqueNum_string;

                  db.collection('landmarks').findOne({'id':newUnique,'world':worldVal}, function(err, data){
                    if (data){
                      console.log('entry found!');
                      uniqueNumber++;
                      next();
                    }
                    else {
                      console.log('entry not found!');
                      next('unique!'); // This is where the looping is stopped
                    }
                  });
                },
                function () {
                  saveLandmark(newUnique);
                });
            }
            else {
                saveLandmark(uniqueIDer);
            }
        });
Run Code Online (Sandbox Code Playgroud)

lmj*_*ns3 16

你的break陈述不在循环体内.相反,它是在函数体内,即findOne回调.为了更清楚地看到这一点,暂时使用命名函数作为回调处理程序会很有帮助:

var cb = function(err, data){
    if (data.id){
        uniqueNumber++;
    }
    else {
        saveLandmark(newUnique);
        break;  // not inside a loop!
    }
};

db.collection('landmarks').findOne({'id':uniqueIDer}, function(err, data){
    //if ID exists already
    if (data.id){
        var uniqueNumber = 1;
        while (1) {
            var uniqueNum_string = uniqueNumber.toString(); 
            var newUnique = data.id + uniqueNum_string;
            db.collection('landmarks').findOne({'id':newUnique}, cb);
        }
    }
    else {
        saveLandmark(uniqueIDer);
    }
});
Run Code Online (Sandbox Code Playgroud)

现在很清楚,break回调函数体中不在循环中!我还以其他方式让事情破裂,因为uniqueNumbernewUnique价值不再是范围,但这是一个不同的问题.:)这里要看的重要一点是,函数在代码中引入了一个"硬"边界,很难根据语言的语法很难看到.这就是为什么这种回调编程风格如此难以正确的原因之一.

事实上,这样做要比你原来对代码的尝试所暗示的要困难得多.当您反复调用findOne和分析结果(异步)时,您需要有一种方法可以通过可能的任意层次的回调传递成功信号.

您可以通过使用优秀的async库获得一些帮助,例如https://github.com/caolan/async#whilst.