Async: Async schützt nicht vor Array-Änderungen während der Laufzeit der Funktion

Erstellt am 4. Juli 2014  ·  6Kommentare  ·  Quelle: caolan/async

Wenn Sie einen asynchronen Anruf haben, z. async.each , und während dieser Laufzeit hat das übergebene Array Modifikationen, dann wird es möglicherweise nie beendet oder ruft den Callback zweimal auf.

Beispiel:

async = require "async" 
arr = [1, 2, 3]  
async.each arr, ((i, cb) -> console.log "i"; setImmediate(cb)), (err) -> console.log "done" 
arr.push(4)

Dieses Beispiel durchläuft die 3 ursprünglichen Array-Elemente und gibt i , ruft dann aber nie den Callback auf, da in async.each Folgendes geschieht:

if (completed >= arr.length) {
  callback(null);
}

Beim Betrachten des asynchronen Codes wird ein Vergleich mit arr.length der sich ändern kann ... wäre es nicht besser, die ursprüngliche Array-Länge zu speichern und einen Vergleich damit durchzuführen, um sicherzustellen, dass der abgeschlossene Callback aufgerufen wird ?

Geige:
http://jsfiddle.net/4ysKX/1/

bug

Hilfreichster Kommentar

Hat Async dazu geführt, dass Array-Änderungen nachträglich nicht zugelassen werden? Ich habe einen Anwendungsfall, bei dem es schön wäre, das ursprüngliche Array nachträglich zu ändern, um mehr Elemente als anfänglich zu durchlaufen.

Alle 6 Kommentare

Sie haben Recht - also ändern Sie es nicht. Klonen Sie Ihr Array, bevor Sie es an eine asynchrone Funktion übergeben, wenn Sie es später ändern müssen.

@aearly Ja, das ist eine

Es wäre schwierig, sich vor _jeder_ Array-Änderung zu schützen, ohne die Eingabe zu klonen, zum Beispiel eine synchrone Änderung in der Iteratorfunktion, aber der Schutz vor _asynchroner_ Änderung, die nichts mit der Iteration zu tun hat, sollte auch ohne Klon einfach sein -- wirklich nur nicht davon ausgehen, dass arr.length bleibt nach dem Hochfahren der asynchronen Jobs konstant (Speichern der Länge in einer Variablen vor der Iteration).

(Ich arbeite mit @bradens zusammen – einer von uns wird eine PR mit Tests einreichen, wenn das willkommen ist).

Eine PR mit Tests wäre wünschenswert, aber letztendlich liegt es an @caolan , sie zusammenzuführen.

Der Nachteil dabei ist der zusätzliche Aufwand für das Kopieren des Arrays. Wenn Sie ein großes Array haben oder async.each usw. oft aufrufen, ist es langsamer und benötigt mehr Speicher.

Ich stimme zu, dass eine Array-Kopie zu viel Overhead wäre. Ich schlage vor, dass, da die anfängliche Iteration des Arrays synchron ist, die ursprüngliche Arraylänge gespeichert werden könnte, um sie später zu überprüfen. Auf diese Weise entspricht die Anzahl der Callback-Aufrufe der Anzahl der Iterator-Aufrufe, auch wenn das Array zwischenzeitlich geändert wird. Dies sollte für async.each einfach und ohne Overhead sein, aber ich habe mir die anderen Funktionen noch nicht angesehen. Es wäre schön, wenn alle parallelen Funktionen in diesen Fällen ein konsistentes Verhalten hätten.

Dies ist ein Duplikat von #557.

Hat Async dazu geführt, dass Array-Änderungen nachträglich nicht zugelassen werden? Ich habe einen Anwendungsfall, bei dem es schön wäre, das ursprüngliche Array nachträglich zu ändern, um mehr Elemente als anfänglich zu durchlaufen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen