简体   繁体   中英

Why does Mongoose's JavaScript have both a return and a callback in the same line?

I'm learning Mongoose and callbacks. I thought that callbacks are used in place of returns, so it's either callbacks or returns, but not both. Then I stumbled upon this, where a return and cb are in the same line.

// define a schema
var animalSchema = new Schema({ name: String, type: String });

// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function (cb) {
  return this.model('Animal').find({ type: this.type }, cb);
}

var Animal = mongoose.model('Animal', animalSchema);
var dog = new Animal({ type: 'dog' });

dog.findSimilarTypes(function (err, dogs) {
  console.log(dogs); // woof
});

I Googled around and found this SO question with two answers both with callbacks, but one without a return, and one with . Are they both correct? If so, when should I put a return with a callback?

Without a return:

animalSchema.statics.findByName = function (name, cb) {
    this.find({ name: new RegExp(name, 'i') }, cb);
}

With a return:

animalSchema.methods.findSimilarTypes = function (cb) {
  return this.model('Animal').find({ type: this.type }, cb);
}

Typically in asynchronous programming techniques, it is a good practice to use a return statement along with callbacks at specific points. For example, when the code has another callback further down. This prevents accidental execution of multiple callbacks within the same function.

Here is a very simple example:

var failureCallback = function(err) {
    console.log("Failed");
    // do something with err
}

var successCallback = function(data) {
    console.log("Success");
    // do something with data        
}

var asyncFunction = function(failureCallback, successCallback) {
    getDataFromDb(err, data) {
        if(err) {
            failureCallback(err);
        }
    successCallback(data);
    }
}

In this case if there is an error, the first callback will definitely be called, but the second callback may also be called simultaneously. So the console output might be:

Failed
Success

To prevent this, you simply add a return statement to the failureCallback:

var asyncFunction = function(failureCallback, successCallback) {
    getDataFromDb(err, data) {
        if(err) {
            return failureCallback(err);
        }
    successCallback(data);
    }
}

Therefore, it is not the case that you can only use return or callback but not both. In fact in some case you must use them together.

All of this to say that, it is possible that in the case of your Mongoose examples, it may be a requirement by the function (although it does not seem so) but it may as well be a force of habit of the original author to use return along with callback. Depending on the context, both are correct. Using return could be either a necessary or unnecessary precaution in these use cases.

With a return and callback on the same line you are "forcing" program to return from your function. If you just use callback, code afterwards would sometimes still get executed.

Example:

someAsyncFunction(err, data) { 
    if(err){ 
       return callback(err)
     } 
     /* do some code with your data */ 
     callback()

That's an interesting difference. Typically callbacks are used as a replacement for returns, but there is usually nothing technically wrong with having an extra return present - Mongoose would probably just ignore the returned data.

My guess would be that the returns are present for consistency with other methods that don't use callbacks. Like the following:

personSchema.virtual('name.full').get(function () {
  return this.name.first + ' ' + this.name.last;
});

Take this with a grain of salt - in my search of the Mongoose codebase I couldn't find any reason to include a return. All in all, though, I'd have it anyway because it can't hurt and that's how mongoose documents it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM