pre save hook: какова последовательность обратных вызовов в мангусте

Я хотел бы увеличить счетчик в обратном вызове перед сохранением. Я нашел этот stackoverflow действительно полезным для этого: Поддерживает ли Mongoose метод Mongodb `findAndModify`?

Я хотел бы использовать метод findAndModify. Но когда я реализую статику, моя последовательность обратных вызовов не соответствует ожиданиям. Я всегда делаю предварительное сохранение, а затем выполняю findAndModify, но я хотел бы выполнить findAndModify между началом и концом хука предварительного сохранения. Если я определяю общий метод с обратным вызовом, он работает, как и ожидалось.

работал также с параметром done хука предварительного сохранения без какого-либо другого результата

Что мне здесь не хватает

Мой код выглядит так:

var mongoose = require('mongoose');
var should = require('should');

mongoose.connect("localhost","test_db");

var CommentSchema = new mongoose.Schema({
  content:    {type:String},
  created_at: {type:Date, default:Date.now},
  _post:{type:mongoose.Schema.ObjectId,ref:'Post'}

});

var PostSchema = new mongoose.Schema({
  title:    {type:String},
  content:  {type:String},
  comments: [{type:mongoose.Schema.ObjectId, ref:'Comment'}],
  counter: {type:Number}

    });

PostSchema.statics.findAndModify= function(query,sort,doc,options,callback){
  return this.collection.findAndModify(query,sort,doc,options,callback);
 }

PostSchema.statics.test_me = function(clb){
   console.log("test_me");
   clb();
}
CommentSchema.pre('save',function(next,done){
  console.log("enter pre save comment");
  if(this.isNew){
   Post.findAndModify({_id:this._post},[],{$inc:{count:1}},{new:true},function(err,post){
    console.log("enter find-and-modify!");
    console.log(post);
   });
  Post.test_me(function(){
    console.log("callback of test_me");
  });
  console.log("exit pre save comment");

    next();
  }
});

var Post = mongoose.model('Post',PostSchema);
var Comment = mongoose.model('Comment',CommentSchema);

var post = new Post({title:"hello world"});
var comment = new Comment({content:"1st comment",_post:post});
post.comments.push(comment);

  var id = post.id;
  console.log(id);
  post.save(function(err){
    comment.save(function(err){
        Post.find({_id:id })
          .populate('comments')
          .exec(function(err,result){
          console.log("--------------- result -----------------");
          console.log(result);
          });
    });
  });

Это результат моей командной строки:

5049f0d2e21547430a000001
enter pre save comment
test_me
callback of test_me
exit pre save comment
enter find-and-modify!
{ __v: 0,
  _id: 5049f0d2e21547430a000001,
  comments: [ 5049f0d2e21547430a000002 ],
  count: 1,
  title: 'hello world' }
--------------- result -----------------
[ { __v: 0,
    _id: 5049f0d2e21547430a000001,
    count: 1,
    title: 'hello world',
    comments: 
     [ { content: '1st comment',
         _post: 5049f0d2e21547430a000001,
         _id: 5049f0d2e21547430a000002,
         __v: 0,
         created_at: Fri Sep 07 2012 15:04:18 GMT+0200 (CEST) } ] } ]

РЕДАКТИРОВАТЬ: я не хочу знать, как выполнить findAndModify с test_me в последовательности. Я хочу знать, почему findAndMody входит после завершения предварительного сохранения. Даже он встроен и должен работать, как показано в методе test_me. Таким образом, метод test_me должен иллюстрировать, что асинхронный метод должен работать вложенным... но findAndModify нет... как показывает мой вывод командной строки... он всегда входит в findAndModify после выхода из предварительного сохранения, даже когда я использую done() Перезвони...


person silverfighter    schedule 07.09.2012    source источник


Ответы (1)


Поскольку мы имеем дело с асинхронностью, она будет работать

console.log("enter pre save comment");
if(this.isNew){
  Post.findAndModify({_id:this._post},[],{$inc:{count:1}},{new:true},function(err,post){
    console.log("enter find-and-modify!");
    console.log(post);
  });
  Post.test_me(function(){
    console.log("callback of test_me");
  });
  console.log("exit pre save comment");
  next();
}

один за другим, не дожидаясь его выполнения или ответа, прежде чем перейти к следующему. Поскольку Post.findAndModify() выполняется дольше, все, что находится в функции обратного вызова, будет выполнено после всего, что находится вне функции обратного вызова.

Если вы хотите, чтобы он выполнял больше по порядку

console.log("enter pre save comment");
if(this.isNew){
  Post.findAndModify({_id:this._post},[],{$inc:{count:1}},{new:true},function(err,post){
    console.log("enter find-and-modify!");
    console.log(post);
    Post.test_me(function(){
      console.log("callback of test_me");
      console.log("exit pre save comment");
      next();
    });
  });     
}
person Last Rose Studios    schedule 07.09.2012
comment
спасибо за ваш ответ ... да, я знаю причину, но и это имеет смысл, но как я мог этого избежать? даже когда я передаю обратный вызов done в хуке перед сохранением, он не работает - person silverfighter; 08.09.2012
comment
если вы хотите, чтобы он выполнялся по порядку, либо используйте async.js для получения серии, либо вложите свои обратные вызовы. - person Last Rose Studios; 08.09.2012
comment
извините за недоразумение. Я отредактировал вопрос, чтобы, надеюсь, иметь больше смысла. Я хотел бы знать, почему findAndModify всегда входит, когда предварительное сохранение выходит... - person silverfighter; 08.09.2012
comment
он выполняет next() асинхронно с вашим findAndModify, что означает, что он не ждет завершения findAndModify, прежде чем перейти к следующей функции. - person Last Rose Studios; 08.09.2012
comment
Да, я тоже так думал, но это не работает... собственный метод findAndModify ведет себя иначе, чем мой собственный асинхронный метод. - person silverfighter; 08.09.2012
comment
@silverfighter Я не знаю точного порядка обратных вызовов (между двумя коллекциями), но на основе вашей схемы, где каждый документ указывает друг на друга, кажется, что вы хотели бы: 1- сначала сохранить сообщение, 2- удалить встроенные комментарии коллекции из документа Post, в котором хранятся идентификаторы комментариев, и вместо этого добавьте индекс в коллекцию комментариев для поля _post. Это даст более простую логику - person Monica Wilkinson; 13.09.2012