Async: Möglichkeit, unverarbeitete Elemente aus async.map() zu ermitteln, nachdem ein Fehler ausgegeben wurde

Erstellt am 10. Juli 2017  ·  5Kommentare  ·  Quelle: caolan/async

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?

question

Hilfreichster Kommentar

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.

Alle 5 Kommentare

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!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen