Ich beschäftige mich mit der asynchronen / wartenden Funktion von Knoten 7 und stolpere immer wieder über Code wie diesen
function getQuote() {
let quote = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
return quote;
}
async function main() {
try {
var quote = await getQuote();
console.log(quote);
} catch (error) {
console.error(error);
}
}
main();
Dies scheint die einzige Möglichkeit zu sein, mit async / await aufzulösen / abzulehnen oder zurückzugeben / zu werfen. V8 optimiert jedoch den Code in try / catch-Blöcken nicht?!
Gibt es Alternativen?
node.js
async-await
ecmascript-2017
Patrick
quelle
quelle
Antworten:
Alternativen
Eine Alternative dazu:
wäre so etwas, wenn man Versprechen explizit verwendet:
oder so ähnlich, unter Verwendung des Continuation-Passing-Stils:
Originalbeispiel
Ihr ursprünglicher Code setzt die Ausführung aus und wartet, bis das zurückgegebene Versprechen erfüllt ist
getQuote()
. Anschließend wird die Ausführung fortgesetzt und der zurückgegebene Wert in geschriebenvar quote
und dann gedruckt, wenn das Versprechen aufgelöst wurde, oder es wird eine Ausnahme ausgelöst und der catch-Block ausgeführt, der den Fehler druckt, wenn das Versprechen abgelehnt wurde.Mit der Promise-API können Sie dasselbe direkt wie im zweiten Beispiel tun.
Performance
Nun zur Aufführung. Lass es uns testen!
Ich habe gerade diesen Code geschrieben -
f1()
gibt1
als Rückgabewert,f2()
wirft1
als Ausnahme:Rufen wir jetzt den gleichen Code millionenfach auf, zuerst mit
f1()
:Und dann wechseln wir
f1()
zuf2()
:Dies ist das Ergebnis, für das ich bekommen habe
f1
:Dafür habe ich
f2
:Es scheint, dass Sie in einem Single-Thread-Prozess etwa 2 Millionen Würfe pro Sekunde ausführen können. Wenn Sie mehr als das tun, müssen Sie sich möglicherweise darum kümmern.
Zusammenfassung
Ich würde mir über solche Dinge in Node keine Sorgen machen. Wenn solche Dinge häufig verwendet werden, werden sie irgendwann von den V8-, SpiderMonkey- oder Chakra-Teams optimiert und jeder wird folgen - es ist nicht so, als wäre es nicht als Prinzip optimiert, es ist einfach kein Problem.
Selbst wenn es nicht optimiert ist, würde ich dennoch argumentieren, dass Sie, wenn Sie Ihre CPU in Node maximal nutzen, Ihre Zahl wahrscheinlich in C schreiben sollten - dafür sind unter anderem die nativen Addons gedacht. Oder vielleicht wären Dinge wie node.native besser für den Job geeignet als Node.js.
Ich frage mich, was ein Anwendungsfall wäre, der so viele Ausnahmen auslösen muss. Normalerweise ist das Auslösen einer Ausnahme anstelle der Rückgabe eines Werts eine Ausnahme.
quelle
try catch
und nicht aus dem Auslösen einer Ausnahme. Obwohl die Zahlen klein sind, ist es nach Ihren Tests fast zehnmal langsamer, was nicht unerheblich ist.Eine Alternative zum Try-Catch-Block ist wait-to-js lib. Ich benutze es oft. Beispielsweise:
Diese Syntax ist im Vergleich zu Try-Catch viel sauberer.
quelle
Alternative ähnlich der Fehlerbehandlung in Golang
Da async / await Versprechen unter der Haube verwendet, können Sie eine kleine Dienstprogrammfunktion wie die folgende schreiben:
Importieren Sie es dann, wann immer Sie Fehler abfangen müssen, und schließen Sie Ihre asynchrone Funktion ein, die ein Versprechen zurückgibt.
quelle
Anstatt eine mögliche Variable zu deklarieren, um einen Fehler oben zu halten, können Sie dies auch tun
Dies funktioniert jedoch nicht, wenn so etwas wie ein TypeError- oder Reference-Fehler ausgelöst wird. Sie können jedoch sicherstellen, dass es sich um einen regelmäßigen Fehler handelt
Ich bevorzuge es, alles in einen großen Try-Catch-Block zu packen, in dem mehrere Versprechen erstellt werden. Dies kann es umständlich machen, den Fehler speziell für das Versprechen zu behandeln, das ihn erstellt hat. Die Alternative sind mehrere Try-Catch-Blöcke, die ich gleichermaßen umständlich finde
quelle
Eine sauberere Alternative wäre die folgende:
Aufgrund der Tatsache, dass jede asynchrone Funktion technisch ein Versprechen ist
Sie können Funktionen Catches hinzufügen, wenn Sie sie mit wait aufrufen
Sie müssen nicht versuchen, zu fangen, da alle Versprechungsfehler behandelt werden und Sie keine Codefehler haben. Sie können dies im übergeordneten Element weglassen!
Nehmen wir an, Sie arbeiten mit Mongodb. Wenn ein Fehler auftritt, ziehen Sie es möglicherweise vor, ihn in der aufrufenden Funktion zu behandeln, als Wrapper zu erstellen oder Try-Catches zu verwenden.
quelle
Ich würde gerne so machen :)
Es ist ähnlich wie beim Umgang mit Fehlern
co
quelle
await
!catch
Auf diese Weise ist es meiner Erfahrung nach gefährlich. Jeder Fehler, der im gesamten Stapel ausgelöst wird, wird abgefangen, nicht nur ein Fehler aus diesem Versprechen (was wahrscheinlich nicht das ist, was Sie wollen).Das zweite Argument für ein Versprechen ist bereits ein Rückruf zur Ablehnung / zum Scheitern. Es ist besser und sicherer, das stattdessen zu verwenden.
Hier ist ein typsicherer typsicherer Einzeiler, den ich geschrieben habe, um dies zu handhaben:
quelle