[英]Node.js - Inserting into MongoDB with a callback
我正在嘗試使用async
的waterfall
方法將一些數據插入MongoDB集合中,以確保一切按正確的順序進行。 最初,我的數據以錯誤的順序插入到MongoDB中,經過一段時間我才意識到這是因為我的insert
異步運行,所以我無法保證以正確的順序保存數據。
所以這是我的async.waterfall
:
async.waterfall([
function(callback) {
request.get(apiUrl, function(error, response, body) {
if (!error && response.statusCode == 200) {
data = JSON.parse(body);
callback(error, data.items);
}
});
},
function(data, callback) {
removeInvalidItems(data);
var items = convertToObj(data);
callback(null, items);
},
function(items, callback) {
console.log(items);
// Insert to collection here
}
], function (err, result) {
// do something here
});
因此,在瀑布的最后一個功能上,我已記錄了要控制台的items
,並且它以正確的順序顯示數據。 所以現在,我要做的就是將數據插入到我的集合中,然后在回調中關閉連接,然后從瀑布中移出到最終function
。 很容易吧? 好吧,這就是我現在正在嘗試的方法:
MongoClient.connect(config.db, function(err, db) {
if (err) {
console.log(err);
} else {
console.log("Connected correctly to server");
db.collection('items').insert(items, function(err, result) {
if (err) {
console.log(err);
}
db.close();
callback(null, 'done');
});
}
});
db.close()
和callback(null, 'done')
應該在收到回調后關閉連接並移出瀑布。 但是我似乎得到的只是RangeError: Maximum call stack size exceeded
。 我已經嘗試了所有可以想到的方法,但無法將此插入與回調一起使用並移出瀑布。
有人可以幫忙嗎?
這個項目集合的大小是多少? 它可以超過調用堆棧的大小嗎? 要運行當前大小,請執行以下操作:
node --v8-options | grep -B0 -A1 stack_size
默認大小是492 kB(對於32位)和984 kB(對於64位)。
要增加調用堆棧的大小,請嘗試使用參數啟動節點:
node --max-stack-size={your-desired-size-in-bytes}
考慮到節點可能沒有時間清除每個瀑布回調之間的調用棧。 嘗試在nextTick上運行回調:
async.waterfall([
function(callback) {
request.get(apiUrl, function(error, response, body) {
if (!error && response.statusCode == 200) {
data = JSON.parse(body);
callback(error, data.items);
}
});
},
function(data, callback) {
removeInvalidItems(data);
var items = convertToObj(data);
process.nextTick(function() { // callback on next tick
callback(null, items);
});
},
function(items, callback) {
console.log(items);
// Insert to collection here
}
], function (err, result) {
// do something here
});
應該為async.waterfall()的每個任務調用所有回調。 僅在您的第一個瀑布任務成功的情況下才調用它……而在第三個瀑布任務中根本沒有調用它。
這兩個調用沒有回調:
removeInvalidItems(data);
items = convertToObj(data);
所以我假設它們不是異步的。 而且由於它們不是異步的,因此您不必將它們作為async.waterfall()的單獨任務。 因此,這是修改后的代碼(我假設您的數據轉換正確):
async.waterfall([
function(callback) {
request.get(apiUrl, function(error, response, body) {
var data;
if (!error && response.statusCode == 200) {
data = JSON.parse(body);
return callback(null, data.items);
}
callback(error || response); // error or statusCode !== 200
});
},
function(data, callback) {
var items;
// There is no callback for these, so I'm assuming they are not asynchronous
removeInvalidItems(data);
items = convertToObj(data);
MongoClient.connect(config.db, function(err, db) {
if (err) {
console.log(err);
return callback(err);
}
console.log("Connected correctly to server");
db.collection('items').insert(items, function(err, result) {
if (err || !result) {
console.log(err);
db.close();
return callback(err || {message: 'There is a problem inserting.'});
}
db.close();
callback(null);
});
});
}
], function (err, result) {
if (err) {
console.log(err);
} else {
console.log('done');
}
});
我已經找到了答案,以我自己的問題在這里 。 問題是,當我將數據批量插入MongoDB時,我收到了Maximum call stack size exceeded
錯誤。 根據名為User
的Mongoose模式,我在運行db.collection('something').insert(data, function()....
時使用的數據數組是Users
數組,因此該data
數組中的每個項目都是創建為var item = new User({});
顯然,MongoDB不喜歡這樣。我認為這是插入數據的正確方法,因為在生產中這就是我將如何使用數據(使用User
對象) 。
為了糾正這個問題,我簡單地更換var item = new User({})
與var item = {}
這樣我只是創建一個新的JavaScript對象。 這樣可以很好地工作,並且可以按照正確的順序將數據插入數據庫中,而不會出錯。 多虧寫了其他答案的人們,我才使用這些答案來修復和改善回調!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.