Tracks
/
Elixir
Elixir
/
Lehrplan
/
Try/Rescue
Tr

Try/Rescue in Elixir

1 Übung

Über Try/Rescue

try .. rescue kannst du verwenden, um Fehler abzufangen und auszuwerten, die in einem Block ausgelöst werden.

Zum Beispiel:

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end
  • Zeile 1: Der Block wird mit try deklariert.
  • Zeile 2: Hier steht der Funktionsaufruf, der einen Fehler erzeugen kann, in diesem Fall rufen wir raise/1 auf.
  • Zeile 4: Im rescue-Abschnitt gleichen wir den Modul-Namen des ausgelösten Fehlers mit einem Muster ab.
    • auf der linken Seite von ->:
      • e wird dem Fehler-Struct zugeordnet.
      • in ist ein Schlüsselwort.
      • RuntimeError ist das Modul, mit dem abgeglichen wird, es kann aber mit jedem Fehlermodul abgeglichen werden, oder mit _ für alle Fehler.
    • auf der rechten Seite:
      • die Anweisungen, die ausgeführt werden, wenn der Fehler übereinstimmt.

Fehler-Structs

Fehler (manchmal auch „Exceptions“ genannt), die du auf diese Weise auffängst, sind Structs. Verschiedene Fehler-Structs haben verschiedene Schlüssel. Im „Exceptions“-Abschnitt der Standardbibliothek findest du eine Liste aller vordefinierten Fehler.

# ArithmeticError caused by division by zero
%ArithmeticError{message: "bad argument in arithmetic expression"}

# Protocol.UndefinedError caused by passing `nil` to `Enum.count/1`
%Protocol.UndefinedError{description: "", protocol: Enumerable, value: nil}

In Elixir fängst du Fehler nur sehr selten ab. Normalerweise protokollierst du den abgefangenen Fehler oder schickst ihn an einen externen Monitoring-Dienst und löst ihn dann erneut aus. Das bedeutet, dass uns die interne Struktur des jeweiligen Fehler-Structs normalerweise nicht interessiert.

Das Exceptions-Konzept beschreibt, wie du eigene Fehler-Structs definierst.

Vermeide Anti-Patterns

  • Vermeide Programmiermuster, die Fehler zur Steuerung des logischen Ablaufs verwenden. Das ist in Elixir ein Anti-Pattern.

    # Avoid using errors for control-flow.
    try do
      {:ok, value} = MyModule.janky_function()
      "All good! #{value}."
    rescue
      e in RuntimeError ->
        reason = e.message
        "Uh oh! #{reason}."
    end
    
    # Rather, use control-flow structures for control-flow.
    case MyModule.janky_function() do
      {:ok, value} -> "All good! #{value}."
      {:error, reason} -> "Uh oh! #{reason}."
    end
    

Auslösen oder nicht auslösen, das ist hier die Frage

Wie es in Elixirs Einstiegsleitfaden steht:

Es liegt an deiner Anwendung zu entscheiden, ob ein Fehler beim [Ausführen einer Aktion] außergewöhnlich ist oder nicht. Deshalb schreibt Elixir [...] Funktionen keine Exceptions vor. Stattdessen überlässt es dem Entwickler, den besten Weg zu wählen, um fortzufahren.

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab

Lerne Try/Rescue