Angenommen, ich habe den folgenden Code.
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if(denominator === 0){
reject("Cannot divide by 0");
return; //superfluous?
}
resolve(numerator / denominator);
});
}
Wenn mein Ziel darin besteht, reject
frühzeitig auszusteigen, sollte ich es mir dann auch zur Gewohnheit machen, return
sofort danach zu gehen?
Antworten:
Der
return
Zweck besteht darin, die Ausführung der Funktion nach der Zurückweisung zu beenden und die Ausführung des Codes danach zu verhindern.In diesem Fall wird die
resolve(numerator / denominator);
Ausführung verhindert , was nicht unbedingt erforderlich ist. Es ist jedoch weiterhin vorzuziehen, die Ausführung zu beenden, um eine mögliche Falle in der Zukunft zu verhindern. Darüber hinaus empfiehlt es sich, das unnötige Ausführen von Code zu verhindern.Hintergrund
Ein Versprechen kann in einem von drei Zuständen sein:
Wenn ein Versprechen erfüllt oder abgelehnt wird, bleibt es auf unbestimmte Zeit in diesem Zustand (erledigt). Die Ablehnung eines erfüllten Versprechens oder die Erfüllung eines abgelehnten Versprechens hat also keine Wirkung.
Dieses Beispiel-Snippet zeigt, dass das Versprechen zwar abgelehnt wurde, aber abgelehnt wurde.
Warum müssen wir also zurückkehren?
Obwohl wir einen festgelegten Versprechungsstatus nicht ändern können, wird die Ausführung des Restes der Funktion durch Ablehnen oder Auflösen nicht gestoppt. Die Funktion kann Code enthalten, der verwirrende Ergebnisse erzeugt. Beispielsweise:
Selbst wenn die Funktion derzeit keinen solchen Code enthält, entsteht eine mögliche zukünftige Falle. Ein zukünftiger Refactor ignoriert möglicherweise die Tatsache, dass der Code nach Ablehnung des Versprechens noch ausgeführt wird und schwer zu debuggen ist.
Beenden der Ausführung nach dem Auflösen / Ablehnen:
Dies ist Standard-JS-Kontrollflussmaterial.
resolve
/reject
:Code-Snippet anzeigen
resolve
/reject
- Da der Rückgabewert des Rückrufs ignoriert wird, können wir eine Zeile speichern, indem wir die Zurückweisungs- / Auflösungsanweisung zurückgeben:Code-Snippet anzeigen
Code-Snippet anzeigen
Ich bevorzuge eine der
return
Optionen, da der Code flacher ist.quelle
return
ist oder nicht, da er nach dem Festlegen eines Versprechensstatus nicht mehr geändert werden kann, sodass ein Aufrufresolve()
nach dem Aufrufreject()
nur einige zusätzliche CPU-Zyklen verwendet. Ich selbst würde dasreturn
nur unter dem Gesichtspunkt der Code-Sauberkeit und -Effizienz verwenden, aber es ist in diesem speziellen Beispiel nicht erforderlich.Promise.try(() => { })
anstelle von neuem Versprechen und vermeiden Sie es, Anrufe aufzulösen / abzulehnen. Stattdessen könnten Sie einfach schreiben, dassreturn denominator === 0 ? throw 'Cannot divide by zero' : numerator / denominator;
ichPromise.try
ein Mittel benutze , um ein Versprechen zu starten und Versprechen zu eliminieren, die in problematische Try / Catch-Blöcke eingewickelt sind.reject
, der etwas Teueres bewirkt, wie die Verbindung zu Datenbanken oder API-Endpunkten? Dies ist alles unnötig und kostet Sie Geld und Ressourcen, insbesondere wenn Sie beispielsweise eine Verbindung zu einer AWS-Datenbank oder einem API-Gateway-Endpunkt herstellen. In diesem Fall würden Sie definitiv eine Rückgabe verwenden, um zu verhindern, dass unnötiger Code ausgeführt wird.return
.Eine übliche Redewendung, die Ihre Tasse Tee sein kann oder nicht, besteht darin, das
return
mit dem zu kombinierenreject
, um gleichzeitig das Versprechen abzulehnen und die Funktion zu verlassen, so dass der Rest der Funktion einschließlich desresolve
nicht ausgeführt wird. Wenn Ihnen dieser Stil gefällt, kann Ihr Code dadurch etwas kompakter werden.Dies funktioniert gut , weil das Versprechen Konstruktor nichts mit einem Rückgabewert der Fall ist, und in jedem Fall
resolve
undreject
Rückkehr nichts.Dieselbe Redewendung kann mit dem in einer anderen Antwort gezeigten Rückrufstil verwendet werden:
Auch dies funktioniert einwandfrei, da die anrufende Person
divide
nicht erwartet, dass sie etwas zurückgibt, und nichts mit dem Rückgabewert tut.quelle
reject
Status zurückzugebenTechnisch wird es hier nicht benötigt 1 - weil ein Versprechen ausschließlich und nur einmal gelöst oder abgelehnt werden kann . Das erste Promise-Ergebnis gewinnt und jedes nachfolgende Ergebnis wird ignoriert. Dies unterscheidet sich von Rückrufen im Knotenstil.
Abgesehen davon ist es eine gute saubere Praxis , sicherzustellen, dass genau eine aufgerufen wird, wenn dies praktikabel ist, und zwar in diesem Fall, da keine weitere asynchrone / verzögerte Verarbeitung erfolgt. Die Entscheidung, "früh zurückzukehren", unterscheidet sich nicht von der Beendigung einer Funktion nach Abschluss ihrer Arbeit - im Gegensatz zur Fortsetzung einer nicht verwandten oder unnötigen Verarbeitung.
Die Rückkehr zum richtigen Zeitpunkt (oder die anderweitige Verwendung von Bedingungen, um die Ausführung des "anderen" Falls zu vermeiden) verringert die Wahrscheinlichkeit, dass Code versehentlich in einem ungültigen Zustand ausgeführt wird oder unerwünschte Nebenwirkungen auftreten. und als solches macht es Code weniger anfällig für "unerwartetes Brechen".
1 Diese technische Antwort hängt auch davon ab, dass in diesem Fall der Code nach der "Rückgabe", falls er weggelassen wird, keine Nebenwirkungen hervorruft. JavaScript teilt sich glücklich durch Null und gibt entweder + Infinity / -Infinity oder NaN zurück.
quelle
Wenn Sie nach einer Auflösung / Ablehnung nicht "zurückkehren", können schlimme Dinge (wie eine Seitenumleitung) passieren, nachdem Sie beabsichtigt haben, dass sie beendet werden. Quelle: Ich bin darauf gestoßen.
quelle
Die Antwort von Ori erklärt bereits, dass dies nicht notwendig ist,
return
aber eine gute Praxis ist. Beachten Sie, dass der Versprechen-Konstruktor ausfallsicher ist, sodass er später im Pfad übergebene ausgelöste Ausnahmen ignoriert. Im Wesentlichen treten Nebenwirkungen auf, die Sie nicht leicht beobachten können.Beachten Sie, dass
return
Frühbucher auch bei Rückrufen sehr häufig sind:Während es sich bei Versprechungen um eine gute Praxis handelt, ist dies bei Rückrufen erforderlich . Einige Hinweise zu Ihrem Code:
quelle
In vielen Fällen ist es möglich, Parameter separat zu validieren und ein abgelehntes Versprechen sofort mit Promise.reject (Grund) zurückzugeben .
quelle