2

Assuming I have the following in a function:

exports.addnames = function(req, res) {
    var names = ["Kelley", "Amy", "Mark"];

    for(var i = 0; i < names.length; i++) {
        (function (name_now) {
            Person.findOne({ name: name_now},
                function(err, doc) {
                    if(!err && !doc) {
                        var personDoc = new PersonDoc();
                        personDoc.name = name_now;
                        console.log(personDoc.name);
                        personDoc.save(function(err) {});
                    } else if(!err) {
                        console.log("Person is in the system");
                    } else {
                        console.log("ERROR: " + err);
                    }
                }
            );   
        )(names[i]);
    }

My issue is after I save the names, I want to return the results:

Person.find({}, function(err, doc) {    
    res.json(200, doc);
})

Though I have a callback for names, it appears that the last block of code (Persons.find({})) gets executed before the calls to save all the names is complete... thusly when the user goes to the url in the browser, "doc" is empty... Is there some way I can ensure that the Persons.find({}) is called after the for loop completes?

1 Answer 1

1

The easiest way to do things like this is to use an async library like the aptly named async which can be found at https://github.com/caolan/async.

If you have a list of names that you want to save and then return when complete, it would look like:

// save each of the names asynchronously
async.forEach(names, function(name, done) {
    Person.findOne({name: name},
        function(err, doc) {
            // return immediately if there was an error
            if(err) return done(err);

            // save the person if it doesn't already exist
            if(!doc) {
                var personDoc = new PersonDoc();
                personDoc.name = name;
                console.log(personDoc.name);

                // the async call is complete after the save completes
                return personDoc.save(done);
            } 

            // or if the name is already there, just return successfully
            console.log("Person is in the system");
            done();
        }
    );           
},
// this function is called after all of the names have been saved
// or as soon as an error occurs
function(err) {
    if(err) return console.log('ERROR: ' + err);

    Person.find({}, function(err, doc) {    
        res.json(200, doc);
    })

});
Sign up to request clarification or add additional context in comments.

1 Comment

That means that done is not being called for some reason (I think 1 minute is the async timeOut). You'll need to narrow down what the problem is - you can start with commenting out Person.findOne entirely and just call done(); immediately. The final function should be called immediately.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.