Das Problem ist wie folgt. Ich habe ein Array von Objekten wie so:Wie kann ich diese verschachtelte asynchrone Schleife verbessern?
let myObj = [
{'db1':['doc1','doc2','doc3']},
{'db2':['doc4','doc5']},
{'db3':['doc7','doc8','doc9','doc10']}
]
Beachten Sie, dass dies eine Datenstruktur, entschied ich mich für das Problem zu bedienen und kann geändert werden, wenn es die allgemeine Umsetzung verbessern. Die tatsächlichen db- und doc-IDs werden aus einer Textdatei gelesen, die wie folgt formatiert ist.
"db1","doc1"
"db1","doc2"
...
Meine App wird synchron durch die Datenbankliste iterieren. Innerhalb jeder db-Iteration wird eine asynchrone Iteration der Dokumentliste stattfinden. Jedes Dokument wird abgerufen, verarbeitet und in der Datenbank gespeichert.
Also grundsätzlich bei jeder gegebenen Instanz: eine db, aber mehrere Dokumente.
Ich habe eine Arbeits Umsetzung der oben etwa so:
dbIterator: die synchrone äußeren Schleife THS iterieren. Der an docIterator
übergebene Rückruf löst die nächste Iteration aus.
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: die asynchrone Schleife docs iterieren. Der Callback cb
wird aufgerufen, nachdem alle Dokumente verarbeitet wurden. Dies geschieht über das docsProcessed
und docsToBeProcessed
Variablen verfolgt
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: verwendet zu verarbeiten und ein individuelles Dokument zu speichern. Dies gibt ein Versprechen, das gelöst wird, wenn die Dokumentenverarbeitung, was wiederum Schritten erfolgt docsProcessed
und bedingt (docsProcessed >= docsToBeProcessed
) ruft den Anruf in 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();
}
})
};
zurückgegeben, wie erwartet Das funktioniert aber für mich diese Implementierung ist suboptimal und unordentlich. Ich bin mir ziemlich sicher, dass dies verbessert werden kann und vor allem eine Chance, Lösungen für synchrone und asynchrone Probleme besser zu verstehen und zu implementieren.
Ich bin offen für konstruktive Kritik. Wie kann das verbessert werden?
Ein guter Platz für Codeüberprüfungen ist https://codereview.stackexchange.com/. Stimme für die Zeit und Mühe ab, die du für die Formulierung dieses Artikels aufgewendet hast, –
Ist es "Docs" oder "DocIds"? – Bergi
Da Sie mit Versprechen arbeiten: Verwenden Sie kein Callback-Argument in Ihrer 'docIterator'-Funktion. Gib ein Versprechen zurück! Außerdem müssen Sie nicht all diesen Prozess selbst zählen - verwenden Sie einfach "Promise.all". – Bergi