我怎样才能改善这个嵌套的asynchronous循环?

问题如下。 我有这样的对象数组:

let myObj = [ {'db1':['doc1','doc2','doc3']}, {'db2':['doc4','doc5']}, {'db3':['doc7','doc8','doc9','doc10']} ] 

请注意,这是我决定用于解决问题的数据结构,如果可以改进整体实施,则可以对其进行更改。 实际的数据库和文档ID是从格式如下的文本文件中读取的。

 "db1","doc1" "db1","doc2" ... 

我的应用程序将同步遍历数据库列表。 在每个数据库迭代中,将会有一个文档列表的asynchronous迭代。 每个文件将被检索,处理并保存回数据库。

所以基本上在任何给定的实例:一个分贝,但多个文件。

我有一个像上面这样的工作实现:

dbIterator :迭代dbs的同步外部循环。 传递给docIterator的callback将触发下一次迭代。

 const dbIterator = function (x) { if (x < myObj.length) { let dbObj = myObj[x]; let dbId = Object.keys(dbObj)[0]; docIterator(dbId, dbObj[dbId], ()=>merchantIterator(x+1)); } else { logger.info('All dbs processed'); } }; 

docIterator :迭代文档的asynchronous循环。 在处理所有文档之后调用callback函数cb 。 这通过docsProcesseddocsToBeProcessedvariables进行跟踪

 const docIterator = function(dbId, docIds, cb){ //create connection targetConnection = //some config for connection to dbId let docsProcessed = 0; let docsToBeProcessed = docIds.length; //asynchronous iteration of documents docIds.forEach((docId)=>{ getDocument(docId, targetConnection).then((doc)=>{ //process document processDoc(doc, targetConnection).then(()=>{ //if processing is successful if (++docsProcessed >= docsToBeProcessed) { cb(); } }) //if processing fails .catch((e) => { logger.error('error when processing document'); if (++docsProcessed >= docsToBeProcessed) { cb(); } }); }).catch((e)=>{ logger.error('error when retrieving document: '); if (++docsProcessed >= docsToBeProcessed) { cb(); } }); }); }; 

processDoc:用于处理和保存单个文档。 这将返回一个承诺,当文档处理完成后,文档处理完成,然后递增docsProcessed并有条件地( docsProcessed >= docsToBeProcessed )调用callback到docIterator

 const processDoc = function(doc, targetConnection) { return new Promise(function(resolve, reject) { if(shouldThisDocBeProcessed(doc){ let updatedDoc = logic(doc); targetConnection.insert(updatedDoc, updatedDoc._id, function (error, response) { if (!error){ logger.info('updated successfully'); } else { logger.error('error when saving doc'); } resolve(); } ); } else { resolve(); } }) }; 

这个按预期工作,但对我来说,这个实现是次优的和混乱的。 我很确定这可以改进,最重要的是有机会更好地理解和实现同步和asynchronous问题的解决scheme。

我接受build设性的批评。 那么这怎么能改进?

也许这样?

油门的一个示例实现可以在这里find。

 //this should be available in both modules so you can filter const Fail = function(details){this.details=details;}; // docIterator(dbId,docIds) // .then( // results =>{ // const failedResults = results.filter( // result => (result&&result.constructor)===Failed // ); // const successfullResults = results.filter( // result => (result&&result.constructor)!==Failed // ); // } // ) const docIterator = function(dbId, docIds){ //create connection // targetConnection = //some config for connection to dbId let docsProcessed = 0; let docsToBeProcessed = docIds.length; //asynchronous iteration of documents docIds.map( docId => new Promise( (resolve,reject) => //if you use throttled you can do: // max10( // ([docId,targetConnection])=> // getDocument(docId,targetConnection) // )([docId, targetConnection]) getDocument(docId, targetConnection) ) .then( doc => //if this returns nothing then maybe you'd like to return the document processDoc(doc, targetConnection) .then( _ => doc ) ) .catch( err => new fail([err,docId]) ) ) };