在mongoose中,保存时可以避免多层嵌套回调吗

Can multiple layers of nested callbacks when saving be avoided in mongoose?

本文关键字:嵌套 回调 可以避免 mongoose 保存      更新时间:2023-09-26

我有两个集合,第一个集合在第二个集合中有一个id引用文档的数组。

有一个特定的地方,我想创建一个新的DocumentType,然后创建一个引用该DocumentType的新Document,最后更新原始DocumentType以引用新Document

一个DocumentType可以具有多个Documents,但一个Document只能具有单个DocumentType。我之所以想在这两个地方都有参考,是为了简化以后更复杂的查询

我的问题是:有没有比使用这些多个嵌套回调更好的方法来使用mongoose编写它。

我举了一个简单的例子来演示。现实中有更多的数据,因此我不想在DocumentType中嵌入Document,反之亦然。

var DocumentTypeSchema = new Schema({
    name:   String
  , desc:   String
  , documents:  [{type: Schema.ObjectId, ref: 'Document'}]
  , ...
});
var DocumentSchema = new Schema({
    title:    String
  , doctype:  {type: Schema.ObjectId, ref: 'DocumentType'}
  , ...
});
var Document = mongoose.model('Document', DocumentSchema);
var DocumentType = mongoose.model('DocumentType', DocumentTypeSchema);
// Begin the nested callbacks
// Create a document type
var type = new DocumentType({...});
// Save document type
type.save(function(err) {
  // Create new document
  var document = new Document({
      doctype: type.id
    , ...
  });
  // Save document
  document.save(function(err) {
    // Update document type
    DocumentType.update({_id: document.doctype}, {'$addToSet': {documents: document.id}}, function(err) {});
  });
});

感谢您的帮助

我想说,通常没有更好的同步处理方法。Jani提到的async库的series函数是一个很好的方法,但我认为坚持回调结构通常是个好主意——它使作用域非常清晰,并减少了外部依赖性——除非嵌套变得荒谬或需要异步。您的嵌套并不荒谬,尽管您可能会考虑异步并行。如果您正在创建两个新实例并在这两个实例之间保存属性,则没有理由同步进行创建。相反,像这样的东西:

    async.parallel({
        type: function(callback) {
            var type = new DocumentType({...});
            type.save(function(err) {callback(null, type)});
        },
        document: function(callback) {
            var document = new Document({...});
            document.save(function(err) {callback(null, document)});
        }
    },
    function(err, results) {
        results.document.doctype = results.type.id;
        results.document.save();
        DocumentType.update(
          {_id: results.type},
          {'$addToSet': {documents: results.document.id}},
          function(err) {}
        );
    });

它需要额外的节省,坦率地说,对于这样一个性能开销很小的任务来说,这可能很愚蠢,但它说明了异步处理的一个好方法和异步库的多功能性。

您可以使用类似node-async的series函数的东西来逐个运行每个回调。这样你就不必给它们筑巢了。

https://github.com/caolan/async