2014-05-23 70 views
1

在下面的代码中,我尝试用一​​些测试数据填充我的开发数据库。我想先删除所有文件,然后添加新的测试者:奇怪的猫鼬行为 - 文档不会保存到DB

var mongoose = require('mongoose') 
    , Plan = mongoose.model('Plan') 
    , Async = require('async') 

Async.series([ 
    function(callback){ 
     // delete all records 
     Plan.find(function(err,docs){ 
      for (d in docs) 
       Plan.remove(d, function(err) { 
        if (err) console.log("error removing records " + err) 
       }); 
     }); 
     callback(); 
    }, 
    function(callback){ 
     var planArray = [ 
      {title: 'Plan A', body: 'Restaurant Financial Plan'}, 
      {title: 'Plan B', body: 'Coffeeshop Financial Plan'}, 
      {title: 'Plan C', body: 'bar Financial Plan'} 
     ] 

     var arrayLength = planArray.length; 
     for (var i = 0; i < arrayLength; i++) { 
      var p = new Plan(planArray[i]) 
      p.save(function(err, saved){ 
      if (err) 
       {console.log("error creating fixture " + err)} 
      else { 
       console.log(saved) 
      } 
      }) 
     } 
     callback(); 
    } 
]) 

有趣的(奇怪)的行为是这样的: - 代码运行,并删除所有文件,但不增加新的测试者。 - 控制台上没有错误,console.log(已保存)成功地将每个新文档打印到控制台。 - 如果我删除第一个异步功能(删除所有记录) - 那么新文档将保存到数据库中。

猫鼬怪癖或我对异步流程的误解..?

回答

1

我的猜测是后者 - 对异步流程的误解。在完成查找和删除文档之前,调用第一个函数的回调函数。所以,当你仍然在找到并移除它们时,你已经在第二个函数中增加了一些 - 但是这些将在第一个函数中找到并删除。

只有在删除所有文档后,您才需要调用第一个回调函数。尝试把一个async.eachPlan.find回调中:

Async.series([ 
    function(callback){ 
     // delete all records 
     Plan.find(function(err, docs){ 
      Async.each(
       docs, // your array 
       function removeDoc(d, cb) { // iterator function 
        Plan.remove(d, function (err) { 
         if (err) console.log("error removing records " + err); 
         return cb(); 
        }); 
       }, 
       callback // executed after the iterator is done 
      ); 
    }, 
    ... 

顺便说一句,我相信Plan.remove({}, function(err){...})删除所有文件 - 无需遍历每个文档当然,除非你正在做别的事情。

+1

豪尔赫,这完美的作品。也是 - 您无需重复删除所有文档即可.remove {}。我的问题 - 这在猫鼬文档中没有记录。你是怎么找到这个的? – NightOwl

+0

太棒了!至于'.remove({})',你是对的 - 它只是在模型概述中间接地提到http://mongoosejs.com/docs/models.html。 “.remove”调用中的第一个参数指定将删除哪些文档。猫鼬会删除所有符合这些条件的*。这也是MongoDB中本地'.remove()'函数的行为。 –

0

第二个函数在您调用callback()后开始执行,即查找并删除呼叫之前。您必须等到查找和删除完成并调用callback()。 看看从异步的队列方法:https://github.com/caolan/async#queue

2

有几个问题。首先,你有一个for循环,它是异步删除的触发器,但这些循环可能在你的第一个回调被调用之前没有完成。代之以更好地使用Async.each

也似乎有一些函数命名碰撞发生。所以对于这个完整的例子,请参阅以下内容:

var mongoose = require('mongoose'), 
    Async = require('async'), 
    Schema = mongoose.Schema; 

mongoose.connect('mongodb://localhost/test'); 

var planSchema = new Schema({ 
    title: String, 
    body: String 
}); 

var Plan = mongoose.model('Plan',planSchema); 

Async.series([ 
    function(call1) { 
    Plan.find(function(err,docs) { 
     if (err) 
     throw err; 

     if (docs.length > 0) { 
     Async.each(docs, function(d, call2) { 
      Plan.remove(d, function(err) { 
      if (err) 
       throw err; 
      console.log("deleting: " + d); 
      call2(); 
      }); 
     }); 
     } 
    }); 
    call1(); 
    }, 
    function(call3) { 

    var planArray = [ 
     { title: 'Plan A', body: 'Plan A' }, 
     { title: 'Plan B', body: 'Plan B' } 
    ]; 

    var arrayLength = planArray.length; 

    for (var i = 0; i < arrayLength; i++) { 
     var p = new Plan(planArray[i]); 
     p.save(function(err,saved) { 
     if (err) 
      throw err; 

     console.log("saving: " + saved); 

     }); 

    } 
    call3(); 
    } 
]);