Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Illegal break statement (Node.js)

Trying to find unique ID in Node.js and MongoDB, by creating a while loop that queries MongoDB for existing IDs, until a unique value is found. If the ID is already in use, a number is incremented on the end until Mongo returns nothing.

Everything is working, except for the break; statement when a unique ID is found. Node.js returns: SyntaxError: Illegal break statement

The code:

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);
    }

});

What am I doing wrong?

EDIT:

Here's the fixed up code using async if anyone needs it :)

        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);
            }
        });
like image 591
alyx Avatar asked Aug 02 '13 18:08

alyx


1 Answers

Your break statement is not inside the body of a loop. It is, instead, inside the body of a function, namely the findOne callback. To see this more clearly, it can be helpful to temporarily use a named function as your callback handler:

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);
    }
});

It's pretty clear now that the break in the callback function body is not inside a loop! I've also made things break in other ways because the uniqueNumber and newUnique values are no longer in scope, but that's a different issue. :) The important thing to see here is that a function introduces a "hard" boundary in your code that can be difficult to see based purely on the syntax of the language. This is one of the reasons why this callback style of programming can be so tricky to get right.

In fact, it's much more difficult to do this than your original attempt at the code would imply. You'll need to have a way of passing a success signal up through possibly arbitrary layers of callbacks as you repeatedly call findOne and analyze the result (asynchronously).

You might get some help with this by using the excellent async library, for example https://github.com/caolan/async#whilst.

like image 62
lmjohns3 Avatar answered Oct 10 '22 02:10

lmjohns3