Es gab heute viel Aufsehen über den neuen Vorschlag für einen sicheren Zuweisungsoperator (?=) in JavaScript. Mir gefällt, wie sich JavaScript im Laufe der Zeit verbessert hat, aber das ist auch ein Problem, auf das ich in letzter Zeit in einigen Fällen gestoßen bin. Ich sollte eine schnelle Beispielimplementierung als Funktion erstellen, oder?
Falls Sie den Vorschlag noch nicht gelesen haben, hier ist, was er vorschlägt:
const [error, value] ?= maybeThrows();
Der neue ?=-Operator würde dem Aufruf der rechten Seite der Zuweisung in einem Try/Catch-Block entsprechen und ein Array zurückgeben. Der erste Wert des zurückgegebenen Arrays wäre ein Fehler, wenn etwas innerhalb der Zuweisung ausgelöst würde, und der zweite Wert wäre das Ergebnis der Zuweisung, wenn nichts ausgelöst würde.
Ich stoße häufig auf Code, der sich in Bezug auf Zuweisungen und Try/Catch-Blöcke ziemlich hässlich anfühlt. Dinge wie diese:
let errorMsg; try { maybeThrow(); } catch (e) { errorMsg = "An error message"; }
Um mit const auf errorMsg außerhalb des try/catch-Blocks zuzugreifen, müssen Sie es außerhalb des Blocks definieren.
Der einfachste Fall ist hier die Handhabung nicht-asynchroner Funktionen. Ich konnte
aufpeitschen
einige Testfälle und eine Funktion namens tryCatch im Handumdrehen:
function tryCatch(fn, ...args) { try { return [undefined, fn.apply(null, args)] } catch (e) { return [e, undefined]; } } function throws() { throw new Error("It threw"); } // returns a sum // prints [ undefined, 2 ] console.log(tryCatch(Math.sqrt, 4)); // returns an error // prints [ Error: 'It threw', undefined ] console.log(tryCatch(throws));
tryCatch ruft die Funktion mit den angegebenen Argumenten auf, die in einen Try/Catch-Block eingeschlossen sind. Es gibt entsprechend [undefiniert, Ergebnis] zurück, wenn nichts innerhalb der Funktion ausgelöst wird, und [Fehler, undefiniert], wenn etwas ausgelöst wird.
Beachten Sie, dass Sie mit tryCatch auch eine anonyme Funktion verwenden können, wenn Sie noch keine Funktion zum Aufrufen bereit haben.
console.log(tryCatch(() => { throw new Error("It threw"); }));
Asynchrone Funktionen werden etwas kniffliger. Eine Idee, die ich ursprünglich hatte, war,
zu schreiben
eine vollständig asynchrone Version, vielleicht asyncTryCatch genannt, aber wo liegt darin die Herausforderung? Das ist eine völlig sinnlose Erkundung! Hier ist eine Implementierung von tryCatch, die sowohl mit asynchronen als auch mit nicht asynchronen Funktionen funktioniert:
function tryCatch(fn, ...args) { try { const result = fn.apply(null, args); if (result.then) { return new Promise(resolve => { result .then(v => resolve([undefined, v])) .catch(e => resolve([e, undefined])) }); } return [undefined, result]; } catch (e) { return [e, undefined]; } } function throws() { throw new Error("It threw"); } async function asyncSum(first, second) { return first second; } async function asyncThrows() { throw new Error("It throws async"); } // returns a sum // prints [ undefined, 2 ] console.log(tryCatch(Math.sqrt, 4)); // returns an error // prints [ Error: 'It threw', undefined ] console.log(tryCatch(throws)); // returns a promise resolving to value // prints [ undefined, 3 ] console.log(await tryCatch(asyncSum, 1, 2)); // returns a promise resolving to error // prints [ Error: 'It throws async', undefined ] console.log(await tryCatch(asyncThrows));
Es sieht der Originalversion sehr ähnlich, enthält aber etwas Promise-basierten Code
zur Sicherheit eingeworfen. Mit dieser Implementierung können Sie tryCatch aufrufen, wenn Sie eine nicht asynchrone Funktion aufrufen, und dann waiting tryCatch aufrufen, wenn Sie eine asynchrone Funktion aufrufen.
Sehen wir uns den Promise-Teil an:
if (result.then) { return new Promise(resolve => { result .then(v => resolve([undefined, v])) .catch(e => resolve([e, undefined])) }); }
if (result.then) prüft, ob die angegebene Funktion (aufgerufen mit apply) ein Promise zurückgegeben hat. Wenn ja, müssen wir selbst ein Versprechen zurückgeben.
Der Aufruf von result.then(v => Auflösung([undefiniert, v])) bewirkt, dass das Versprechen in den Wert aufgelöst wird, den die angegebene Funktion zurückgegeben hat, wenn nichts ausgelöst wird.
.catch(e => Auflösung([e, undefiniert])) ist etwas kniffliger. Ich habe ursprünglich geschrieben
es als .catch(e => Reject([e, undefiniert])), aber das führt zu einem nicht abgefangenen Fehler
aus tryCatch herausfallen. Wir müssen hier eine Lösung finden, da wir ein
zurückgeben.
Array, löst keinen Fehler aus.
Ich habe ziemlich regelmäßig Fälle, in denen ich versuchen/fangen muss, aber das Gefühl habe, dass
Ein expliziter Try/Catch-Block nimmt eine Menge Platz in Anspruch und ist bei Scoping-Zuweisungen lästig. Ich bin mir nicht sicher, ob ich es verwenden werde oder nicht, aber das war eine lustige kleine Erkundung.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3