2013-03-08 86 views
0

我會嘗試儘可能簡潔 - 貓鼬似乎不保存記錄,直到整個腳本結束,即使在保存()部分異步調用:爲什麼Mongoose不能在腳本執行時保存記錄?

var reallyBigData = require('./data.json'); 

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    newObj.x = data.x; 
    newObj.save(); 
}; 

this.on('importData', importData); 

for(var i in reallyBigData) { 
    this.emit('importData', reallyBigData[i]); 
}; 

這是一個粗略的簡化,但你明白了。當我運行腳本並查詢Mongo時,腳本運行時沒有看到任何記錄。如果我將數字限制爲30,並將其導入快速結束,然後我會看到記錄。

爲什麼Mongoose不在腳本執行時保存每條記錄?

回答

2

問題是x.save()(或newObj.save())是異步的,你沒有任何東西在等待它完成,而不是Node本身。

是異步的,它只有開始任務更新MongoDB中的集合並立即退出。它實際上不會「」直到後來,當一個可選的回調將被稱爲:

x.save(function (err, instance) { 
    // at this point, it either erred or saved 
}); 

但是,它有可能爲x.save()近瞬間完成。時間結束的記錄數量較少意味着你有一個競爭條件 - 這將首先完成:對MongoDB或Node/V8執行代碼塊的查詢?

而且,使用EventEmitter,至少在這裏採樣的方式不足以使循環異步,因爲您仍然同步地執行事件,並且emit()將同步循環處理任何處理程序。

但是,有許多「控制流程」庫可用,可以幫助。這些措施包括promises實現,futures和迭代器一樣async

var reallyBigData = require('./data.json'); 

async.each(Object.keys(reallyBigData), 
    function (key, callback) { 
     new Obj({ x: reallyBigData[key] }).save(callback); 
    }, 

    function (err, results) { 
     // called with an `err` or an `Array` of `results` (saved `Obj`s) 
    } 
); 
+0

有趣的是,我通過扔掉貓鼬並使用本地驅動程序解決了這個問題。我想知道Mongoose是否執行某種查詢緩存。我會更多地嘗試它,但似乎Mongoose在大循環結束之前沒有處理任何插入請求。 – James 2013-03-11 17:05:48

+0

@James是的,Mongoose會排隊查詢,以便您可以*同步調用它們並讓它們異步運行。這是「* callback hell *」的一種可能的解決方案。此外,本地驅動程序仍然是異步的,你仍然應該使用'insert()'和一個異步迭代器進行回調。 – 2013-03-11 17:20:16

0

首先,我認爲你有一個討厭的錯誤在這裏:

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    Obj.x = data.x; 
    x.save(); 
}; 

原本應該最有可能讀作:

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    newObj.x = data.x; 
    newObj.save(); 
}; 

由於它看起來像是試圖在您的模式上運行,而不是在模式中運行,而不是在模式中「新建」的模型。那有意義嗎?或者,也許你就是這麼想的,而你只是錯過了打字?正如我沒有看到你將如何從你有的代碼中獲得預期的結果,而不管它是如何執行到數據庫的。也許正如你現在所做的那樣,它很難發現模型已經改變了價值,或者它沒有通過驗證。

+0

你說得對。這是我的問題,而不是在代碼中的拼寫錯誤。不過謝謝。 – James 2013-03-11 17:03:49

相關問題