Hallo,
Gibt es bei Verwendung von map(...) eine Möglichkeit, bei der Behandlung eines von der Iteratee-Funktion ausgegebenen Fehlers zu bestimmen, wie viele Elemente aus der bereitgestellten Sammlung noch nicht verarbeitet wurden?
Ich verwende map
, um mehrere ausgehende HTTP-Anfragen (mithilfe der Bibliothek des Knotens request
) für ein Array verschiedener URLs usw. auszuführen. Bei einer dieser Anfragen erhalte ich möglicherweise einen bestimmten Fehler vom Zielserver, mit dem ich umgehen kann, aber ich möchte dann das aktuelle Element, an dem gearbeitet wird, und dann alle verbleibenden, die map
noch nicht abgeholt hat, erneut verarbeiten.
Ich habe mich gefragt, ob ich vielleicht für jedes Element in meiner Sammlung, an dem erfolgreich (ohne Fehler) gearbeitet wurde, ein Flag setzen und dann, wenn der Fehler ausgegeben wird, an dem ich interessiert bin, entsprechend damit umgehen sollte. Dann erstellen Sie vielleicht ein neues Array aus den Elementen, bei denen das Flag auf false gesetzt ist, für die noch nicht verarbeiteten und führen Sie weitere map
über diese aus, um sicherzustellen, dass ich den ursprünglichen letzten Callback aus der ursprünglichen Map aufrufe.
Ich bin mir nicht sicher, ob dies sinnvoll ist, aber gibt es eine Möglichkeit, das zu erreichen, was ich oben beschrieben habe?
Hallo @parky128 , danke für die Frage!
Würde es funktionieren, das iteratee
mit reflect
umschließen? reflect
geht immer ein Ergebnis Objekt an den callback
, so dass selbst wenn eine der iteratee
Funktionen Fehler, map
beenden würde. Dann könnten Sie einfach über das results
-Objekt von map
iterieren, prüfen, welche eine error
-Eigenschaft haben, und es dann entsprechend behandeln. Sie müssten keine Artikel erneut bearbeiten, die map
möglicherweise nicht abgeholt haben.
async.map(coll, async.reflect(function(val, callback) {
// your request code
}, function(err, results) {
// err will always be null now
results.forEach(function(result, i) {
if (result.error) {
// your code for handling errors
// if `coll` is an array, you could access the value that caused
// this error through `coll[i]` as `map` preserves the order for arrays
} else {
// otherwise `result.value` will contain the result of that `iteratee` call
}
});
});
Andernfalls gibt map
zur Beantwortung Ihrer Frage immer ein array
. Sie könnten über dieses Array iterieren und prüfen, welche Werte undefined
. Diese beziehen sich auf Elemente, die entweder fehlerhaft waren, undefined
an ihre callback
, in Bearbeitung waren, als die error
auftraten oder noch nicht gestartet wurden. Der reflect
Ansatz ist jedoch wahrscheinlich die sicherere Option, da undefined
ein gültiges Ergebnis eines iteratee
Aufrufs sein kann.
Vielen Dank, dass Sie sich die Zeit genommen haben, eine mögliche Lösung anzubieten. Ich möchte eigentlich, dass der letzte Rückruf von async.map aufgerufen wird, sobald eine der iteratee
Funktionsfehler mit dem bestimmten Fehlerfall auftritt, den ich abfangen möchte.
Wenn ich mir die Dokumente ansehe, die ich sehe, kann ich dies erreichen, indem ich einen Fehler an die iteratee-Callback-Funktion übergebe, aber ich frage mich, ob ich im letzten Callback, den async.map aufruft, ob ich dieses Ergebnisobjekt einfach zum Vergleich mit dem Original verwenden könnte sammeln und sehen, was noch zu verarbeiten ist.
Ich möchte nur nicht, dass async.map versucht, andere Anfragen zu verarbeiten, sobald einer davon den Fehlerfall zurückgibt, an dem ich interessiert bin.
Ich möchte nur nicht, dass async.map versucht, andere Anfragen zu verarbeiten, sobald einer davon den Fehlerfall zurückgibt, an dem ich interessiert bin.
Angenommen, Ihr iteratee
ist asynchron, async.map
hat mit der Verarbeitung aller Elemente begonnen, wenn der letzte Rückruf aufgerufen wird. Sie könnten möglicherweise das Ergebnisobjekt mit der Sammlung vergleichen, um zu sehen, welche Elemente noch nicht verarbeitet wurden, aber das hat auch seine Fallstricke. Zum Beispiel müssten Sie dies synchron tun, mit dem gleichen Tick wird der letzte Callback aufgerufen, da das Ergebnisobjekt mit der Auflösung von iteratee
aktualisiert wird.
Du könntest es mit mapSeries
versuchen. mapSeries
führt jeweils nur eine Anfrage aus. dh es ruft das nächste Element nur auf, wenn das aktuelle die Verarbeitung beendet hat (im Gegensatz zum Starten aller auf einmal). Das heißt, wenn ein Fehler auftritt und der letzte Callback aufgerufen wird, werden keine iteratee
s mehr ausgeführt. Sie können dann die Ergebnisse mit der Sammlung vergleichen, um zu sehen, welche Elemente noch nicht verarbeitet wurden. Dies ist immer noch ein kleiner Workaround, aber es ist schöner als async.map
. Der Hauptnachteil dieses Ansatzes besteht jedoch darin, dass Anfragen nicht mehr parallel bearbeitet werden.
Wenn Ihre Sammlung beispielsweise ein Array ist
async.mapSeries(coll, function(val, callback) {
// your iteratee function
}, function(err, results) {
if (err) {
// unprocessItems will include the item that errored.
var unprocessItems = coll.slice(results.length - 1);
// handle the unprocessedItems
}
});
Hmm Ok, ja, meine Iteratee-Funktion ist asynchron, da sie die Anforderungsbibliothek verwendet, um eine ausgehende http-Anfrage zu stellen und ich mit dem Ergebnis davon zurückrufe. Wenn ich also sage, dass 10 Elemente zu durchlaufen sind, 4 erfolgreich waren und das 5. fehlgeschlagen ist, würde ich dann den Rückruf zur iteratee-Funktion mit einem Fehlerparameter aufrufen, sollte dies bedeuten, dass das Ergebnisobjekt im letzten Rückruf zu async.map nur enthält die 4 erfolgreichen Ergebnisse?
Wenn dies der Fall ist, werde ich vorerst damit leben, dass es immer noch alle ausgehenden Anrufe tätigt. Ich kann auf der ganzen Linie mein Array in kleinere Arrays aufteilen und kleinere async.maps innerhalb einer MapSeries ausführen, um den anfänglichen Treffer auf den Zielserver zu minimieren, den die Anforderungen treffen.
@hargasinski - Ich habe den async.reflect
Ansatz verwendet und das funktioniert gut für mich, gibt mir volle Sichtbarkeit aller Elemente, die einen Fehler verursacht haben :+1:
Vielen Dank!
Hilfreichster Kommentar
Hallo @parky128 , danke für die Frage!
Würde es funktionieren, das
iteratee
mitreflect
umschließen?reflect
geht immer ein Ergebnis Objekt an dencallback
, so dass selbst wenn eine deriteratee
Funktionen Fehler,map
beenden würde. Dann könnten Sie einfach über dasresults
-Objekt vonmap
iterieren, prüfen, welche eineerror
-Eigenschaft haben, und es dann entsprechend behandeln. Sie müssten keine Artikel erneut bearbeiten, diemap
möglicherweise nicht abgeholt haben.Andernfalls gibt
map
zur Beantwortung Ihrer Frage immer einarray
. Sie könnten über dieses Array iterieren und prüfen, welche Werteundefined
. Diese beziehen sich auf Elemente, die entweder fehlerhaft waren,undefined
an ihrecallback
, in Bearbeitung waren, als dieerror
auftraten oder noch nicht gestartet wurden. Derreflect
Ansatz ist jedoch wahrscheinlich die sicherere Option, daundefined
ein gültiges Ergebnis einesiteratee
Aufrufs sein kann.