2014-05-23 45 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(); 
    } 
]);