2017-12-28 11 views
1

Bis Async/Await wenn wir alle X Sekunden, um eine wiederkehrende Sache N mal machen benötigt hatten wir die Wahl zwischen einem for-Schleife, die ein settimeout oder verwenden, um einen Wrapper um setinterval wickelt die Anzahl der Male zu zählen, es ausgeführt wurde und klar es.Ist es in Ordnung, setTimeout in einer for-Schleife zu erwarten?

Aber mit Asynchron erwarten ist es in Ordnung, dies zu tun:

async function newFashion() { 
    for (let i = 0; i < 10; i++) { 
    console.log(i); 
    await sleep(1000); 
    } 
    console.log("Finish"); 
} 
newFashion(); // 0 1 2 3 4 5 6 7 8 9 Finish 

function oldFashion() { 
    for (let i = 0; i < 10; i++) { 
    setTimeout(() => { 
     console.log(i); 
    }, i * 1000); 
    } 
    console.log("Finish"); 
} 
oldFashion(); // Finish 0 1 2 3 4 5 6 7 8 9 

function sleep(time) { 
    return new Promise((resolve) => { 
    setTimeout(resolve, time); 
    }); 
} 

Ich weiß, dass die beiden nicht gleich verhalten. oldFashion() nicht tatsächlich "pausieren" in der Schleife, aber eigentlich die 10 setTimeout() während iterating aufrufen, so im Grunde füllt er die Ereignisschleife mit 10 setTimeout().

newFashion() verhält sich jedoch so, wie es sein sollte, er hört auf zu iterieren, wenn er auf die wartet, aber ich bin mir nicht sicher, wie genau das funktioniert.

Also was ist besser, füllen die Ereignisschleife mit N setTimeout(), oder warten aufeinander? Und was passiert eigentlich in newFashion()?

EDIT: Um etwas genauer zu sein, was ist der Gewinn jede Methode in Bezug auf Leistung? Wenn N klein ist? Wenn N riesig ist?

+0

Ich glaube nicht, dass es Probleme mit Ihrem neuen Code gibt, und ich persönlich finde es viel einfacher zu lesen. – Gerrit0

+2

Persönlich bevorzuge ich 'const delay = time => neues Versprechen (res => setTimeout (res, time)); ';) –

+0

@CodyG. Haha, wir müssen es hier einfach halten;) – Smirow

Antwort

1

Und was geschieht eigentlich in NewFashion()?

Der await Ausdruck bewirkt, dass der Aufruf von newFashion Funktion zu unterbrechen, bis sleep Ergebnis der Funktion, die ein Versprechen ist, wird aufgelöst oder abgelehnt werden. Nach dem Auflösen oder Zurückweisen wird der Rest des Codes fortgesetzt.

Also was ist besser, füllen die Ereignisschleife mit N setTimeout(), oder warten nacheinander?

Wie Sie sehen können, ist der async/await Teil besser lesbar. Wenn die Umgebung ES8 unterstützt, können Sie sie frei verwenden. async/await Teil auch vertraute Programmierer, die in Javascript aus solchen Sprachen wie C# kam, die auch async/await für asynchrone Programmierung verwendet. Und für sie ist es praktischer, mit async/await statt dem for loop Beispiel zu arbeiten, das Sie haben.

+0

Die Codeausführung nach einem abgelehnten Versprechen wird nicht fortgesetzt. 'await' löst den Grund für die Ablehnung aus, wenn das Operandenversprechen abgelehnt wird. Der Wurf verwirft dann das Versprechen, das vom Aufruf der Async-Funktion zurückgegeben wird, es sei denn, es wird in einem try/catch-Block abgefangen. – traktor53

+0

@ traktor53 Sie haben Recht. Aber das Steuerelement wird sowieso auf die Async-Funktion zurückgeführt. Welches kann den Fehler behandeln oder es durch Aufrufstack –

2

Hier ist eine bessere Möglichkeit, eine "altmodische" Version zu schreiben. Es bewahrt das erwünschte Verhalten, das "Finish" Log als letztes zu haben, und es ist nicht darauf angewiesen, eine Reihe von Timern sofort in verschiedenen Intervallen in der Zukunft zu setzen.

Das Ganze ist in sich geschlossen und klar.

function betterOldFashion(i, n) { 
 
    if (i < n) { 
 
    console.log(i); 
 
    setTimeout(betterOldFashion, 1000, i+1, n); 
 
    } else { 
 
    console.log("Finish"); 
 
    } 
 
} 
 
betterOldFashion(0, 10);


Ihre vorgeschlagen „altmodische“ Art und Weise weniger lesbar aussieht, weil Sie aus in eine separate Funktion nicht abstrakt Teil des Verhaltens tat, wie Sie mit dem „neuen“ Art und Weise tat , die Sie aus irgendeinem Grund unter den "altmodischen" Weg stellen.

Um den gleichen Vorteil zu geben, hier ist eine Neuschreibung der Art, wie Sie es getan haben, obwohl nicht imperative Schleifen Konstrukte in erster Linie ist besser, IMO.

function oldFashion() { 
 
    for (let i = 0; i < 10; i++) { 
 
    schedule(i, i); 
 
    } 
 
    schedule("Finish", 10); 
 
} 
 
oldFashion(); 
 

 
function schedule(msg, i) { 
 
    setTimeout(() => { 
 
    console.log(msg); 
 
    }, i * 1000); 
 
}


WRT Leistung, das ist in der Regel weniger problematisch für Asynchron-Code, und es ist schwierig zu messen. Die Lösung an der Spitze hat sicherlich die geringste Komplexität, wenn das ein Indikator für Effizienz ist, und Ihre Version des alten Weges muss viele Dinge sofort planen und mehr Hintergrundarbeit schaffen.

+0

werfen Das zweite Code-Snippet ist wirklich schrecklich. So zerbrechlich ... – Bergi

+0

@Bergi: Es ist im Grunde das gleiche wie der OP-Code, der, wie ich vorgeschlagen habe, nicht wünschenswert ist. Ich habe diese Lösung nur überarbeitet, um den Unterschied in der Lesbarkeit zu zeigen, der durch das Verschieben des Codes in eine Funktion erhalten wurde, was das OP für die async/await-Version getan hat. –

Verwandte Themen