为什么 Mongoose 的 JavaScript 在同一行中同时具有 return 和回调?

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

我正在学习 Mongoose 和回调。我认为回调是用来代替 returns 的,所以它要么是回调要么是 returns,但不是两者。然后我偶然发现了这一点,其中 returncb 在同一行。

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

我用 Google 搜索了一下,发现这个 SO 问题有两个答案都带有回调,但是 one without a return, and one with。他们都正确吗?如果是这样,我应该什么时候放一个 return 回调?

没有 return:

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

与 return:

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

这是一个有趣的区别。通常回调被用作 returns 的替代品,但在技术上通常没有额外的 return 出现 - Mongoose 可能会忽略 returned 数据。

我的猜测是 return 的存在是为了与不使用回调的其他方法保持一致。像下面这样:

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

对此持保留态度 - in my search of the Mongoose codebase 我找不到任何理由加入 return。总而言之,无论如何,我都会拥有它,因为它不会造成伤害,这就是 mongoose 记录它的方式。

通常在异步编程技术中,在特定点使用 return 语句和回调是一种很好的做法。例如,当代码在更下方有另一个回调时。这可以防止在同一函数内意外执行多个回调。

这是一个非常简单的例子:

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

这种情况下如果出错,肯定会调用第一个回调,但也有可能同时调用第二个回调。所以控制台输出可能是:

Failed
Success

为了防止这种情况,您只需在 failureCallback 中添加一个 return 语句:

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

因此,并非只能使用return或回调而不能同时使用。事实上在某些情况下你必须一起使用它们。

综上所述,就您的 Mongoose 示例而言,这可能是功能的要求(尽管看起来并非如此),但也可能是习惯的力量原作者使用 return 和回调。根据上下文,两者都是正确的。在这些用例中,使用 return 可能是必要的或不必要的预防措施。

在同一行上使用 return 和回调,您可以从您的函数 "forcing" 程序到 return。如果你只是使用回调,后面的代码有时仍然会被执行。

示例:

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