Heim  >  Artikel  >  Web-Frontend  >  Sichere Zuweisung

Sichere Zuweisung

WBOY
WBOYOriginal
2024-09-10 14:30:15487Durchsuche

Safe Assignment

Heute gab es viel Aufregung ü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.

Ein häufiges Try/Catch-Ärgernis

Ich stoße häufig auf Code, der sich bei Zuweisungen und Try/Catch-Blöcken ziemlich hässlich anfühlt. Dinge wie diese:

let errorMsg;

try {
  maybeThrow();
} catch (e) {
  errorMsg = "An error message";
}

Um auf errorMsg außerhalb des try/catch-Blocks mit const zuzugreifen, müssen Sie es außerhalb des Blocks definieren.

Eine nicht-asynchrone Implementierung

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 innerhalb der Funktion nichts 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");
}));

Umgang mit asynchronen Funktionen

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 ähnelt stark der Originalversion, enthält jedoch 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 => restart([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 => restart([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 eine
zurücksenden Array, es wird kein Fehler ausgegeben.

Und schließlich

Ich habe ziemlich regelmäßig Fälle, in denen ich es versuchen/fangen muss, aber Lust darauf habe
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.

Das obige ist der detaillierte Inhalt vonSichere Zuweisung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Bereitstellung mit ArbeiternNächster Artikel:Bereitstellung mit Arbeitern