2017-06-18 52 views
0

想象下面的脚本循环的NodeJS和MongoDB保存引起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 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 db ,这将达到我的MongoDB Maxx连接。 那么我现在希望做的是:

创建一个空数组

var myarray = [] // ok 

push each "details" to myarray 

myarray.push(details) 

但我的问题是因为是的NodeJS异步的,我需要等待Ÿ循环结束保存到db

因此,如何在发送myarray到保存函数之前等待Y循环完成。 没有实现等待时间..?

我使用回调试过,保证没有任何成功..

+0

y = Number(y)是不必要的,因为y已经是一个数字...... –

回答

0

你可以使用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(); 
}); 
0

很复杂的东西。我希望这有效,因为我无法测试它。我基本上是大量使用嵌套Promise.all s,这在你的情况我认为是必要的:

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的数据库conntections。

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

这是一种做事的方法。

但是,这种方式不会扩大生产规模。对于生产,您应该使用连接池。这意味着:

  1. 在程序开始时,连接到mongodb几次并将每个db存储在一个数组中。
  2. 当你做一个插入,你从数组中的一个db
  3. 你与插入完成后,你给db回到阵。
  4. 当阵列中没有可用的db时,您等待其中一个可用。

我想有很多连接池实现可用于mongodb,包括不少本地连接池。只需选择一个。