Javascript Nodejs循环和Mongodb保存导致Mongodb MAx连接
想象一下下面的脚本Javascript Nodejs循环和Mongodb保存导致Mongodb MAx连接,javascript,node.js,mongodb,Javascript,Node.js,Mongodb,想象一下下面的脚本 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
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")
});
});
}
但我的问题是,由于nodeJS是异步的,我需要等待y循环的末尾保存到db
那么,在将myarray发送到save函数之前,如何等待Y循环完成呢。
没有等待时间
我尝试过使用callback,promise,但没有成功。您可以使用promise.all。首先,将承诺存储在一个数组中:
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();
});
相当复杂的东西。我希望这能起作用,因为我无法测试它。我基本上大量使用嵌套的
Promise。所有的s,在您的情况下,我认为是必要的:
var起始页=1;
var endPage=40;
var=[];
//进行搜索
对于(变量y=起始页;y<结束页;y++){
searchPromises.push(getresult.from.myapiExample.run());
}
//创建数据库连接
新承诺(功能(解决、拒绝){
连接(url,函数(错误,数据库){
如果(错误){
返回拒绝(错误);
}
解析(数据库);
});
}).then(函数(db){
var collection=db.collection('thebase');
Promise.all(searchPromises).then(函数(dataArray){
//dataArray包含搜索结果数组的数组
var results=dataArray.map(函数(数据){
//数据包含一个搜索结果数组
返回data.results.map(函数(结果){
返回result.getDetails();
});
});
//结果是一个数组,将其展平:
var resultPromises=[].concat.apply([],结果);
返回承诺。全部(结果承诺);
}).然后(函数(结果){
var insertPromises=results.map(函数(结果){
返回新承诺(功能(解决、拒绝){
collection.insert(结果、函数(错误、文档){
如果(错误){
拒绝(错误);
}
解决(文档);
});
});
});
返回承诺。全部(插入承诺);
}).then(功能(docsArray){
//docsArray包含collection.insert中回调的docs参数数组
console.log('所有记录正常');
}).catch(函数(错误){
console.log('无法将数据插入数据库',错误);
});
}).catch(函数(错误){
console.log('无法连接到数据库',错误);
});
这样,您就不必创建40次35次的数据库连接。由于以下事实,您将获得最大连接错误:
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。在程序开始时连接一次db
,并仅在执行完MongoClient之后,才将db
存储在全局变量中。如果开始插入数据,并且只要程序执行,就不会关闭db
,则连接
这是做事的一种方式
但这一方法不会扩大生产规模。对于生产,您应该使用连接池。这意味着:
在程序开始时,您多次连接到mongodb,并将每个db
存储在一个数组中
插入时,从数组中获得一个db
完成插入后,将db
返回给数组
当阵列中没有可用的db
s时,请等待其中一个可用
我想mongodb有很多连接池实现,包括很多本机实现。只选一个。y=Number(y)是不必要的,因为y已经是一个数字了。。。
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")
});
});
}