Avoiding nested callbacks when using MongooseJS I'm diving into the world of nodejs and mongo. I am playing around with a simple app that uses MongooseJS to talk to Mongo. I have been looking at examples and some GitHub projects for references, but the pattern seems very sloppy to me. Is this approach considered normal, or is there a better way?

Here is a sample from the app I am building with my daughter. Those nested callbacks feel like an anti-pattern to me.  Am I wrong? Are there better ways to do it?

//userController.js when a new user registers an account is made and a document is cloned that will be their new "pet";

var Pet = require("models/pet.js");
var User = require("models/user.js");

exports.register = function (req, res, next) {
    var user = new User({
        username: req.body.username,
        password: req.body.password
    });

    user.save(function (err) {
        if (err) {
            next(err);
            return;
        }

        Pet.findOne({
            "name": "Egg",
            "ownerId": "&lt;&lt;system&gt;&gt;"
        }, function (err, pet) {
            if (err){
                next(err);
                return;
            }
            Pet.clonePetForUser(user._id, pet._id, function (err) {
                if (err) {
                    next(err);
                    return;
                }
                res.json({message: 'User created'});
            })
        }); 
    });
};
Yes you're right, there are better solutions. For example you could use promises instead of callbacks since mongoose operations can return promises according to the documentation.

Your example with promises:

var Pet = require("models/pet.js");
var User = require("models/user.js");

exports.register = function (req, res, next) {

    var user = new User({
        username: req.body.username,
        password: req.body.password
    });

    user.save()
        .then(function () {
            return Pet.findOne({
                "name": "Egg",
                "ownerId": "&lt;&lt;system&gt;&gt;"
            });
        })
        .then(function (pet) {
            return Pet.clonePetForUser(user._id, pet._id);
        })
        .then(function () {
            res.json({message: 'User created'});
        })
        .catch(function (err) {
            console.error(err);
            next(err);
        });

});


You can write your own method to return a promise. Instead of:

petSchema.statics.clonePetForUser = function (userId, petId, callback) {
     this.find({ }, callback);
};


You can write:

petSchema.statics.clonePetForUser = function (userId, petId) {
    return this.find({ });
};