Fehler sind gut. Der Autor des Materials, dessen Übersetzung wir heute veröffentlichen, ist zuversichtlich, dass diese Idee allen bekannt ist. Auf den ersten Blick scheinen die Fehler beängstigend. Sie können von einer Art Verlust begleitet sein. Ein Fehler in der Öffentlichkeit schadet der Autorität desjenigen, der ihn begangen hat. Aber wenn wir Fehler machen, lernen wir daraus. Wenn wir das nächste Mal in eine Situation geraten, in der wir uns zuvor falsch verhalten haben, tun wir alles nach Bedarf.

Oben haben wir über die Fehler gesprochen, die Menschen im Alltag machen. Programmierfehler sind etwas anderes. Fehlermeldungen helfen uns, den Code zu verbessern. Sie ermöglichen es uns, Benutzer über unsere Projekte zu informieren, dass ein Fehler aufgetreten ist, und Benutzern möglicherweise mitzuteilen, wie sie sich verhalten sollen, damit keine Fehler mehr auftreten.
Dieses JavaScript-Material zur Fehlerbehandlung ist in drei Teile unterteilt. Zunächst geben wir einen allgemeinen Überblick über das Fehlerbehandlungssystem in JavaScript und sprechen über Fehlerobjekte. Danach suchen wir nach der Antwort auf die Frage, was mit Fehlern im Servercode zu tun ist (insbesondere bei Verwendung des Bundles Node.js + Express.js). Als nächstes diskutieren wir die Fehlerbehandlung in React.js. Die Frameworks, die hier betrachtet werden, werden aufgrund ihrer enormen Beliebtheit ausgewählt. Die hier beschriebenen Prinzipien für die Arbeit mit Fehlern sind jedoch universell. Selbst wenn Sie Express und React nicht verwenden, können Sie das Gelernte problemlos auf die Tools anwenden, mit denen Sie arbeiten.
Der Code für das in diesem Material verwendete Demo-Projekt befindet sich in
diesem Repository.
1. Fehler in JavaScript und universelle Möglichkeiten, mit ihnen zu arbeiten
Wenn in Ihrem Code ein Fehler aufgetreten ist, können Sie die folgende Konstruktion verwenden.
throw new Error('something went wrong')
Während der Ausführung dieses Befehls wird eine Instanz des
Fehlerobjekts erstellt und eine Ausnahme mit diesem Objekt generiert (oder, wie sie sagen, "ausgelöst"). Die
throw- Anweisung kann Ausnahmen auslösen, die beliebige Ausdrücke enthalten. In diesem Fall wird die Ausführung des Skripts gestoppt, wenn keine Maßnahmen zur Behebung des Fehlers ergriffen wurden.
Anfänger-JS-Programmierer verwenden normalerweise nicht die
throw
Anweisung. Sie stoßen normalerweise auf Ausnahmen, die entweder von der Sprachlaufzeit oder von Bibliotheken von Drittanbietern ausgelöst werden. In diesem Fall gelangt so etwas wie ein
ReferenceError: fs is not defined
in die Konsole
ReferenceError: fs is not defined
und die Programmausführung wird gestoppt.
▍Objektfehler
Instanzen des
Error
haben mehrere Eigenschaften, die wir verwenden können. Die erste Eigenschaft, die uns interessiert, ist
message
. Hier wird die Zeile abgerufen, die als Argument an den Fehlerkonstruktor übergeben werden kann. Im Folgenden wird beispielsweise gezeigt, wie Sie das Fehlerobjekt instanziieren und die vom Konstruktor übergebene Zeichenfolge durch Zugriff auf seine
message
an die Konsole ausgeben.
const myError = new Error('please improve your code') console.log(myError.message)
Die zweite sehr wichtige Eigenschaft des Objekts ist die Verfolgung des Fehlerstapels. Dies ist eine
stack
. Wenn Sie sich dem zuwenden, können Sie den Aufrufstapel (Fehlerverlauf) anzeigen, der die Abfolge der Vorgänge anzeigt, die zu einer Fehlfunktion des Programms geführt haben. Dies ermöglicht uns insbesondere zu verstehen, welche Datei den fehlerhaften Code enthält, und zu sehen, welche Folge von Funktionsaufrufen zu dem Fehler geführt hat. Hier ist ein Beispiel dafür, was Sie sehen können, wenn Sie auf die
stack
Eigenschaft zugreifen.
Error: please improve your code at Object.<anonymous> (/Users/gisderdube/Documents/_projects/hacking.nosync/error-handling/src/general.js:1:79) at Module._compile (internal/modules/cjs/loader.js:689:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10) at Module.load (internal/modules/cjs/loader.js:599:32) at tryModuleLoad (internal/modules/cjs/loader.js:538:12) at Function.Module._load (internal/modules/cjs/loader.js:530:3) at Function.Module.runMain (internal/modules/cjs/loader.js:742:12) at startup (internal/bootstrap/node.js:266:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3)
Hier oben wird eine Fehlermeldung angezeigt, gefolgt von einer Angabe des Codeabschnitts, dessen Ausführung den Fehler verursacht hat. Anschließend wird der Ort beschrieben, von dem aus dieser fehlerhafte Abschnitt aufgerufen wurde. Dies setzt sich in Bezug auf das Fehlercodefragment bis zum „weitesten“ fort.
▍ Generierung und Fehlerbehandlung
Das Erstellen einer Instanz des
Error
, dh das Ausführen eines Befehls des Formulars
new Error()
, führt zu keinen besonderen Konsequenzen. Interessante Dinge beginnen nach dem Anwenden des
throw
zu passieren, was einen Fehler erzeugt. Wie bereits erwähnt, wird die Skriptausführung gestoppt, wenn ein solcher Fehler nicht verarbeitet wird. In diesem Fall spielt es keine Rolle, ob der
throw
Operator vom Programmierer selbst verwendet wurde, ob ein Fehler in einer bestimmten Bibliothek oder in der Sprachlaufzeit (in einem Browser oder in Node.js) aufgetreten ist. Lassen Sie uns über verschiedene Fehlerbehandlungsszenarien sprechen.
Konstruktionsversuch ... fangen
Der
try...catch
ist der einfachste Weg, um häufig vergessene Fehler zu behandeln. Heutzutage wird es jedoch viel intensiver als zuvor verwendet, da es zur Behandlung von Fehlern in
async/await
Konstrukten verwendet werden kann.
Dieser Block kann verwendet werden, um Fehler zu behandeln, die im synchronen Code auftreten. Betrachten Sie ein Beispiel.
const a = 5 try { console.log(b)
Wenn wir in diesem Beispiel den fehlgeschlagenen
console.log(b)
in einen
try...catch
einschließen würden, würde das Skript gestoppt.
▍ endlich blockieren
Manchmal muss Code ausgeführt werden, unabhängig davon, ob ein Fehler aufgetreten ist oder nicht. Dazu können Sie den dritten optionalen Block
finally
im Konstrukt
try...catch
verwenden. Oft entspricht seine Verwendung einem Code, der unmittelbar nach dem
try...catch
, aber in einigen Situationen kann er nützlich sein. Hier ist ein Beispiel für seine Verwendung.
const a = 5 try { console.log(b)
▍Asynchrone Mechanismen - Rückrufe
Bei der Programmierung in JavaScript sollten Sie immer auf asynchron ausgeführte Codeabschnitte achten. Wenn Sie eine asynchrone Funktion haben und ein Fehler darin auftritt, wird das Skript weiterhin ausgeführt. Wenn asynchrone Mechanismen in JS mithilfe von Rückrufen implementiert werden (dies wird übrigens nicht empfohlen), erhält der entsprechende Rückruf (Rückruffunktion) normalerweise zwei Parameter. Dies ist so etwas wie der Parameter
err
, der einen Fehler und ein
result
- mit den Ergebnissen einer asynchronen Operation. Es sieht ungefähr so aus:
myAsyncFunc(someInput, (err, result) => { if(err) return console.error(err)
Wenn im Rückruf ein Fehler auftritt, wird dieser dort als
err
angezeigt. Andernfalls erhält dieser Parameter den Wert
undefined
oder
null
. Wenn sich herausstellt, dass
err
etwas hat, ist es wichtig, darauf zu reagieren, entweder weil in unserem Beispiel der Befehl
return
wird oder
if...else
der Befehl
if...else
und Befehle im
else
Block platziert werden, um mit dem Ergebnis der asynchronen Operation zu arbeiten. Der Punkt ist, im Falle eines Fehlers die Möglichkeit auszuschließen, mit dem Ergebnis, dem
result
, zu arbeiten, der in diesem Fall
undefined
. Das Arbeiten mit diesem Wert kann selbst einen Fehler verursachen, wenn beispielsweise angenommen wird, dass er ein Objekt enthält.
result.data
, dies geschieht, wenn Sie versuchen, das Konstrukt
result.data
oder ähnliches zu verwenden.
▍Asynchrone Mechanismen - Versprechen
Um asynchrone Operationen in JavaScript auszuführen, ist es besser, Versprechen als Rückrufe zu verwenden. Neben der verbesserten Lesbarkeit des Codes gibt es hier erweiterte Fehlerbehandlungsmechanismen. Sie müssen sich nämlich nicht mit dem Fehlerobjekt beschäftigen, das bei der Verwendung von Versprechungen in die Rückruffunktion fallen kann. Zu diesem Zweck ist hier ein spezieller
catch
vorgesehen. Es fängt alle Fehler ab, die in den Versprechungen vor ihm aufgetreten sind, oder alle Fehler, die im Code nach dem vorherigen
catch
aufgetreten sind. Beachten Sie, dass wenn ein Fehler in dem Versprechen auftritt, das keinen zu verarbeitenden
catch
Block enthält, die Ausführung des Skripts nicht gestoppt wird, die Fehlermeldung jedoch nicht besonders lesbar ist.
(node:7741) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: something went wrong (node:7741) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. */
Daher können Sie bei der Arbeit mit Versprechungen immer empfehlen, den Fangblock zu verwenden. Schauen Sie sich ein Beispiel an.
Promise.resolve(1) .then(res => { console.log(res)
▍Asynchrone Mechanismen und versuchen Sie ... zu fangen
Nachdem das Konstrukt
async/await
in JavaScript
async/await
, kehrten wir zur klassischen Methode der Fehlerbehandlung zurück - um zu
try...catch...finally
. Die Behandlung von Fehlern mit diesem Ansatz ist sehr einfach und bequem. Betrachten Sie ein Beispiel.
;(async function() { try { await someFuncThatThrowsAnError() } catch (err) { console.error(err)
Bei diesem Ansatz werden Fehler im asynchronen Code genauso behandelt wie im synchronen. Infolgedessen können Sie jetzt bei Bedarf in einem einzelnen Fangblock einen größeren Bereich von Fehlern behandeln.
2. Generieren und Verarbeiten von Fehlern im Servercode
Nachdem wir nun die Werkzeuge zum Arbeiten mit Fehlern haben, schauen wir uns an, was wir in realen Situationen damit machen können. Das Generieren und korrekte Behandeln von Fehlern ist ein kritischer Aspekt der serverseitigen Programmierung. Es gibt verschiedene Ansätze, um mit Fehlern zu arbeiten. Hier zeigen wir einen Ansatz mit unserem eigenen Konstruktor für Instanzen des
Error
und Fehlercodes, die bequem an das Front-End oder an einen beliebigen Mechanismus mithilfe von Server-APIs übergeben werden. Wie das Backend eines bestimmten Projekts strukturiert ist, spielt keine Rolle, da Sie bei jedem Ansatz dieselben Ideen für die Arbeit mit Fehlern verwenden können.
Als Server-Framework für das Routing verwenden wir Express.js. Überlegen wir uns, welche Struktur wir benötigen, um ein effektives Fehlerbehandlungssystem zu organisieren. Also hier ist was wir brauchen:
- Die universelle Fehlerbehandlung ist ein grundlegender Mechanismus, der zur Behandlung von Fehlern geeignet ist. Während dieser Zeit wird eine Meldung wie "
Something went wrong, please try again or contact us
Der Benutzer wird aufgefordert, den fehlgeschlagenen Vorgang erneut auszuführen oder den Serverbesitzer zu kontaktieren." Dieses System ist nicht besonders intelligent, kann aber zumindest den Benutzer darüber informieren, dass ein Fehler aufgetreten ist. Eine solche Nachricht ist viel besser als "endloser Download" oder ähnliches. - Verarbeiten spezifischer Fehler - Ein Mechanismus, mit dem Sie den Benutzer detailliert über die Ursachen für falsches Systemverhalten informieren und ihm spezifische Ratschläge zur Behebung des Problems geben können. Dies kann beispielsweise auf das Fehlen einiger wichtiger Daten in der Anforderung zurückzuführen sein, die der Benutzer an den Server sendet, oder darauf, dass die Datenbank bereits einen bestimmten Datensatz enthält, den er erneut hinzufügen möchte, und so weiter.
▍ Entwicklung eines eigenen Konstruktors für Fehlerobjekte
Hier verwenden wir die Standardfehlerklasse und erweitern sie. Die Verwendung von Vererbungsmechanismen in JavaScript ist riskant, aber in diesem Fall sind diese Mechanismen sehr nützlich. Warum brauchen wir Vererbung? Tatsache ist, dass wir zum bequemen Debuggen des Codes Informationen über die Ablaufverfolgung des Fehlerstapels benötigen. Durch die Erweiterung der Standardfehlerklasse können wir den Stapel ohne zusätzlichen Aufwand verfolgen. Wir fügen unserem eigenen Fehlerobjekt zwei Eigenschaften hinzu. Die erste ist die
code
Eigenschaft, auf die über eine Struktur des Formulars
err.code
. Die zweite ist die
status
. Es wird der HTTP-Statuscode aufgezeichnet, der an den Client-Teil der Anwendung übertragen werden soll.
So sieht die
CustomError
Klasse aus, deren Code als Modul konzipiert ist.
class CustomError extends Error { constructor(code = 'GENERIC', status = 500, ...params) { super(...params) if (Error.captureStackTrace) { Error.captureStackTrace(this, CustomError) } this.code = code this.status = status } } module.exports = CustomError
▍ Routing
Nachdem unser Fehlerobjekt einsatzbereit ist, müssen wir die Routenstruktur konfigurieren. Wie oben erwähnt, müssen wir einen einheitlichen Ansatz für die Fehlerbehandlung implementieren, der es uns ermöglicht, Fehler für alle Routen gleichermaßen zu behandeln. Standardmäßig unterstützt das Express.js-Framework ein solches Schema nicht vollständig. Tatsache ist, dass alle seine Routen gekapselt sind.
Um dieses Problem zu lösen, können wir unseren eigenen Routenhandler implementieren und die Routenlogik in Form gewöhnlicher Funktionen definieren. Dank dieses Ansatzes fällt die Routenfunktion (oder eine andere Funktion), wenn sie einen Fehler auslöst, in den Routenhandler, der ihn dann an den Client-Teil der Anwendung übergeben kann. Wenn auf dem Server ein Fehler auftritt, planen wir, ihn im folgenden Format an das Front-End zu übertragen, vorausgesetzt, die JSON-API wird dafür verwendet:
{ error: 'SOME_ERROR_CODE', description: 'Something bad happened. Please try again or contact support.' }
Wenn Ihnen zu diesem Zeitpunkt das, was passiert, unverständlich erscheint - keine Sorge - lesen Sie einfach weiter, versuchen Sie, mit dem zu arbeiten, was gerade besprochen wird, und Sie werden es nach und nach herausfinden. Wenn wir über Computertraining sprechen, wird hier der „Top-Down“ -Ansatz verwendet, wenn zuerst allgemeine Ideen diskutiert und dann der Übergang zu Einzelheiten durchgeführt wird.
So sieht der Route-Handler-Code aus.
const express = require('express') const router = express.Router() const CustomError = require('../CustomError') router.use(async (req, res) => { try { const route = require(`.${req.path}`)[req.method] try { const result = route(req)
Wir glauben, dass die Kommentare im Code dies recht gut erklären. Wir hoffen, dass das Lesen bequemer ist als die nachfolgenden Erklärungen zu diesem Code.
Schauen Sie sich nun die Routendatei an.
const CustomError = require('../CustomError') const GET = req => {
In diesen Beispielen wird nichts mit den Abfragen selbst gemacht. Es werden lediglich verschiedene Szenarien für das Auftreten von Fehlern berücksichtigt. So fällt beispielsweise die
GET /city
Anforderung in die
const GET = req =>...
Funktion
const GET = req =>...
, die
POST /city
Anforderung in die
const POST = req =>...
Funktion
const POST = req =>...
und so weiter. Dieses Schema funktioniert auch bei Verwendung von Abfrageparametern. Zum Beispiel für eine Anfrage des Formulars
GET /city?startsWith=R
Im Allgemeinen wurde hier gezeigt, dass das Frontend bei der Verarbeitung von Fehlern entweder einen allgemeinen Fehler erhalten kann, der nur ein Angebot zum erneuten Versuch enthält, oder den Serverbesitzer zu kontaktieren, oder einen Fehler, der mit dem
CustomError
Konstruktor generiert wurde und detaillierte Informationen zum Problem enthält.
Allgemeine Fehlerdaten werden in folgender Form an den Client-Teil der Anwendung gesendet:
{ error: 'GENERIC', description: 'Something went wrong. Please try again or contact support.' }
Der
CustomError
Konstruktor wird folgendermaßen verwendet:
throw new CustomError('MY_CODE', 400, 'Error description')
Dies gibt den folgenden JSON-Code, der an das Frontend übergeben wird:
{ error: 'MY_CODE', description: 'Error description' }
Nachdem wir den Serverteil der Anwendung gründlich bearbeitet haben, fallen nutzlose Fehlerprotokolle nicht mehr in den Clientteil. Stattdessen erhält der Client nützliche Informationen darüber, was schief gelaufen ist.
Vergessen Sie nicht, dass
hier das Repository mit dem hier betrachteten Code liegt. Sie können es herunterladen, damit experimentieren und bei Bedarf an die Anforderungen Ihres Projekts anpassen.
3. Arbeiten Sie mit Fehlern auf dem Client
Jetzt ist es Zeit, den dritten Teil unseres Front-End-Fehlerbehandlungssystems zu beschreiben. Hier müssen zum einen Fehler behandelt werden, die im Client-Teil der Anwendung auftreten, und zum anderen muss der Benutzer über Fehler informiert werden, die auf dem Server auftreten. Wir werden uns zunächst mit der Anzeige von Serverfehlerinformationen befassen. Wie bereits erwähnt, wird in diesem Beispiel die React-Bibliothek verwendet.
▍Speichern Sie Fehlerinformationen im Anwendungsstatus
Wie bei allen anderen Daten können sich Fehler und Fehlermeldungen ändern. Daher ist es sinnvoll, sie in den Status von Komponenten zu versetzen. Wenn die Komponente bereitgestellt wird, werden die Fehlerdaten zurückgesetzt. Wenn der Benutzer die Seite zum ersten Mal sieht, werden keine Fehlermeldungen angezeigt.
Als nächstes müssen Fehler desselben Typs im selben Stil angezeigt werden. In Analogie zum Server können Sie hier 3 Arten von Fehlern unterscheiden.
- Globale Fehler - Diese Kategorie umfasst allgemeine Fehlermeldungen, die vom Server stammen, oder Fehler, die beispielsweise auftreten, wenn der Benutzer in anderen ähnlichen Situationen nicht am System angemeldet ist.
- Spezifische Fehler, die von der Serverseite der Anwendung generiert werden - dies schließt Fehler ein, die vom Server gemeldet werden. Ein ähnlicher Fehler tritt beispielsweise auf, wenn ein Benutzer versucht hat, sich anzumelden und einen Benutzernamen und ein Kennwort an den Server gesendet hat, und der Server ihn darüber informiert hat, dass das Kennwort falsch ist. Solche Dinge werden im Client-Teil der Anwendung nicht überprüft, daher sollten Nachrichten über solche Fehler vom Server kommen.
- Spezifische Fehler, die vom Client-Teil der Anwendung generiert werden. Ein Beispiel für einen solchen Fehler ist eine Nachricht über eine ungültige E-Mail-Adresse, die in das entsprechende Feld eingegeben wurde.
Fehler des zweiten und dritten Typs sind sehr ähnlich. Sie können mit ihnen über den Statusspeicher von Komponenten derselben Ebene arbeiten. Ihr Hauptunterschied besteht darin, dass sie aus verschiedenen Quellen stammen. Im Folgenden wird der Code analysiert und die Arbeit mit ihnen betrachtet.
Es verwendet das integrierte System zum Verwalten des Status der Anwendung in React. Bei Bedarf können Sie jedoch spezielle Lösungen zum Verwalten des Status verwenden, z. B. MobX oder Redux.
▍ Globale Fehler
In der Regel werden solche Fehlermeldungen in der Komponente der höchsten Ebene mit einem Status gespeichert. Sie werden in einem statischen Benutzeroberflächenelement angezeigt. Dies kann ein rotes Kästchen am oberen Bildschirmrand, ein modales Fenster oder etwas anderes sein. Die Umsetzung hängt vom jeweiligen Projekt ab. So sieht die Fehlermeldung aus.
Globale FehlermeldungSchauen Sie sich nun den Code an, der in der Datei
Application.js
gespeichert ist.
import React, { Component } from 'react' import GlobalError from './GlobalError' class Application extends Component { constructor(props) { super(props) this.state = { error: '', } this._resetError = this._resetError.bind(this) this._setError = this._setError.bind(this) } render() { return ( <div className="container"> <GlobalError error={this.state.error} resetError={this._resetError} /> <h1>Handling Errors</h1> </div> ) } _resetError() { this.setState({ error: '' }) } _setError(newError) { this.setState({ error: newError }) } } export default Application
, ,
Application.js
, . , .
GlobalError
,
x
, .
GlobalError
(
GlobalError.js
).
import React, { Component } from 'react' class GlobalError extends Component { render() { if (!this.props.error) return null return ( <div style={{ position: 'fixed', top: 0, left: '50%', transform: 'translateX(-50%)', padding: 10, backgroundColor: '#ffcccc', boxShadow: '0 3px 25px -10px rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', }} > {this.props.error} <i className="material-icons" style={{ cursor: 'pointer' }} onClick={this.props.resetError} > close </font></i> </div> ) } } export default GlobalError
if (!this.props.error) return null
. , . . , , , . , ,
x
, - , .
, ,
_setError
Application.js
. , , , , (
error: 'GENERIC'
). (
GenericErrorReq.js
).
import React, { Component } from 'react' import axios from 'axios' class GenericErrorReq extends Component { constructor(props) { super(props) this._callBackend = this._callBackend.bind(this) } render() { return ( <div> <button onClick={this._callBackend}>Click me to call the backend</button> </div> ) } _callBackend() { axios .post('/api/city') .then(result => {
, . , , . . -, , -, UX-, , — .
▍ ,
, , , .
, . . .
SpecificErrorReq.js
.
import React, { Component } from 'react' import axios from 'axios' import InlineError from './InlineError' class SpecificErrorRequest extends Component { constructor(props) { super(props) this.state = { error: '', } this._callBackend = this._callBackend.bind(this) } render() { return ( <div> <button onClick={this._callBackend}>Delete your city</button> <InlineError error={this.state.error} /> </div> ) } _callBackend() { this.setState({ error: '', }) axios .delete('/api/city') .then(result => { // - , }) .catch(err => { if (err.response.data.error === 'GENERIC') { this.props.setError(err.response.data.description) } else { this.setState({ error: err.response.data.description, }) } }) } } export default SpecificErrorRequest
, , ,
x
. , , . , , — , , , . , , . , , , — .
▍,
, , , . , , - . .
,SpecificErrorFrontend.js
, .
import React, { Component } from 'react' import axios from 'axios' import InlineError from './InlineError' class SpecificErrorRequest extends Component { constructor(props) { super(props) this.state = { error: '', city: '', } this._callBackend = this._callBackend.bind(this) this._changeCity = this._changeCity.bind(this) } render() { return ( <div> <input type="text" value={this.state.city} style={{ marginRight: 15 }} onChange={this._changeCity} /> <button onClick={this._callBackend}>Delete your city</button> <InlineError error={this.state.error} /> </div> ) } _changeCity(e) { this.setState({ error: '', city: e.target.value, }) } _validate() { if (!this.state.city.length) throw new Error('Please provide a city name.') } _callBackend() { this.setState({ error: '', }) try { this._validate() } catch (err) { return this.setState({ error: err.message }) } axios .delete('/api/city') .then(result => { // - , }) .catch(err => { if (err.response.data.error === 'GENERIC') { this.props.setError(err.response.data.description) } else { this.setState({ error: err.response.data.description, }) } }) } } export default SpecificErrorRequest
▍
, , (
GENERIC
), , . , , , , , , , , . .
Zusammenfassung
, , -.
console.error(err)
, , , . -
loglevel .
Liebe Leser! ?
