想象以下脚本
var startPage = 1
var endPage = 40
for (y = startPage; y < endPage ; y++) {
var y = Number(y)
var search = getresult.from.Myapiforexample
search.run().then(function (data) {
//////////////////
/// This will generate 35 results//
var myresult = data.results
for (i = 0; i < myresult.length; i++) {
data.results[i].getDetails().then(function (details) {
savetodb(details)
}, function (err) {
console.error(err);
});
}
}, function (err) {
console.error(err);
});
}
function savetodb(json) {
var getsession = function(db, callback) {
var collection = db.collection('thebase');
collection.insert(data, function (err, docs) {
callback(docs);
db.close();
});
};
MongoClient.connect(url, function(err, db) {
getsession(db, function(docs) {
console.log("Recording ok")
});
});
}
第一个循环(带y)运行40时间每个生成35个结果。 所以我将有40 X 35记录保存到Mongo数据库 这将达到我的mongodb Maxx连接。 所以我要做的是:
创建一个空数组
var myarray = [] // ok
push each "details" to myarray
myarray.push(details)
但我的问题是因为nodeJS是异步的,我需要等待y循环结束才能保存到db
那么在将myarray发送到保存功能之前,我怎么能等待Y循环完成。 没有实现等待时间..?
我尝试使用回调,承诺没有任何成功..
答案 0 :(得分:0)
你可以使用Promise.all。首先将promises存储在一个数组中:
var promises=[];
//in the loop
promises.push(data.results[i].getDetails());
所以现在你可以等待所有这些并保存它们:
Promise.all(promises).then(savetodb);//passes all results to savetodb in an array
您可能希望启用savetodb将数组作为参数,但这取决于您...
但是,不是为每个操作打开新连接,而只需保留一个:
var db=new Promise(function(res,rej){//in global scope
MongoClient.connect(url, function(err, db) {
if(err) return rej(err);
res(db);
});
});
现在,您可以随处访问此连接:
db.then(function(db){
//db is our database
});
你可以像这样实现错误处理:
db.catch(function(err){
console.log("fatal db error. shutting down. "+err);
process.exit();
});
答案 1 :(得分:0)
相当复杂的东西。我希望这有效,因为我无法测试它。我基本上大量使用嵌套的Promise.all
,在我看来我认为是必要的:
var startPage = 1;
var endPage = 40;
var searchPromises = [];
// make the searches
for (var y = startPage; y < endPage; y++) {
searchPromises.push(getresult.from.Myapiforexample.run());
}
// create a database connection
new Promise(function (resolve, reject){
MongoClient.connect(url, function(error, database) {
if (error) {
return reject(error);
}
resolve(database);
});
}).then(function (db) {
var collection = db.collection('thebase');
Promise.all(searchPromises).then(function (dataArray) {
// dataArray contains an array of an array of search results
var results = dataArray.map(function (data) {
// data contains an array of search results
return data.results.map(function (result) {
return result.getDetails();
});
});
// results is an array of arrays, flatten it:
var resultPromises = [].concat.apply([], results);
return Promise.all(resultPromises);
}).then(function (results) {
var insertPromises = results.map(function (result) {
return new Promise(function (resolve, reject) {
collection.insert(result, function (error, docs) {
if (error) {
reject(error);
}
resolve(docs);
});
});
});
return Promise.all(insertPromises);
}).then(function (docsArray) {
// docsArray contains an array of the docs parameter of the callback in collection.insert
console.log('All recordings OK.');
}).catch(function (error) {
console.log('Could not insert data into database', error);
});
}).catch(function (error) {
console.log('Could not connect to database', error);
});
这样,您不必创建40次35个数据库连接。
答案 2 :(得分:0)
由于以下事实,您会收到最大连接错误:
function savetodb(json) {
var getsession = function(db, callback) {
var collection = db.collection('thebase');
collection.insert(data, function (err, docs) {
callback(docs);
db.close();
});
};
MongoClient.connect(url, function(err, db) {
getsession(db, function(docs) {
console.log("Recording ok")
});
});
}
每次调用此getsession
函数时,都会打开一个与mongodb的新连接。并且您大约getsession
次(endPage - startPage) * (data.results.length)
次,这超过了您的mongodb实例接受的最大连接数。
你应该做的是:
您在程序开始时执行MongoClient.connect
一次,将db
存储在全局变量中,并且只有在您完成执行MongoClient.connect
之后才能开始插入数据并且不要只要程序执行,就关闭db
。
这是做事的一种方式。
但是这种方式不会扩大生产规模。对于生产,您应该使用连接池。这意味着:
db
存储在一个数组中。db
db
返回给阵列。db
,则等待其中一个可用。我猜mongodb有很多连接池实现,包括很多原生的实现。只需选一个。