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

时间:2012-01-09 05:07:58

标签: javascript node.js mongodb mongoose

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

我想创建一个新的DocumentType,然后是一个引用Document的新DocumentType,最后更新原始DocumentType以引用新Document

DocumentType可以有多个Documents,但Document只能有一个DocumentType。我想在两个地方都有引用的原因是为了以后简化更复杂的查询。

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

我已经汇总了一个简单的例子来演示。真实的东西中有更多的数据,因此我不想将Document嵌入DocumentType中,反之亦然。

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

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

您可以使用node-async的series函数之类的东西来运行彼此之后的每个回调。这样您就不必嵌套它们。

https://github.com/caolan/async

答案 1 :(得分:1)

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

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

它需要额外的保存,对于像这样的任务而言,这可能很愚蠢,只有很少的性能开销,但它说明了异步处理和异步库的多功能性的好方法。