# Error Handling

In hubble bestehen verschiedene Layer für die Behandlung von Fehlern, die im Zusammenhang mit API Calls aufreten können.

Zum einen gibt es Route-Level Fehler, die beim Routing an eine Middleware zurückgeliefert werden. Da die Middleware dazu dient sicherzustellen, dass die Daten für die Route im Vuex Store bereitstehen für das Rendering, wird stattdessen, die unter ~/layouts/error.vue definierte Error Page angezeigt. Seiten sind in NuxtJS standardmäßig unter ~/pages enthalten und es handelt sich bei der Error Page um einen Spezialfall, der im Abschnitt Error Page (opens new window) der NuxtJS Dokumentation nachgelesen werden kann. Somit kann für diese, unter ~/layouts/ definierte, Seite ein zu verwendendes Layout definiert werden:

// ~/layouts/error.vue
export default {
    layout: 'hubble',
}
1
2
3
4

In der ~/layouts/error.vue existiert eine Unterscheidung je nach Status Code, die per Prop an diese Komponente übergeben wurde (this.error.statusCode) und zur Einbindung einer entsprechenden speziellen Komponente führt. Diese spezielleren Komponenten, die sich am Status Code ausrichten, sind in dem Ordner ~/components/error/ enthalten.

Der Status Code ist Teil des Prop Feldes error:

// ~/layouts/error.vue
props: {
    error: {
        type: Object,
        default: () => {}
    }
}
1
2
3
4
5
6
7

Die übergebene Prop wird ebenfalls als Prop der eingebundenen Komponente weitergereicht:

<!-- ~/layouts/error.vue -->
<template>
    <component :is="errorPage" :error="error" />
</template>
1
2
3
4

Welche Komponete eingebunden wird, ergibt sich aus dem Feld statusCode:

// ~/layouts/error.vue
computed: {
    errorPage() {
        if(this.error.statusCode === 400) {
            return error400;
        }

        if(this.error.statusCode === 401) {
            return error401;
        }
        // & more conditionals
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Falls es keine explizite Angabe eines Status Codes gibt, die an die error() übergeben wurde, dann führt dies zur Anzeige der ~/components/error/default.vue.

Im Folgenden ist ein Beispiel aus der Middleware apiResourceMenu, die für die Bereitstellung der Menüdaten zuständig ist:

// ~/modules/@hubblecommerce/hubble/core/middleware/apiResourceMenu.js
store.dispatch('modApiMenu/getMenu', {})
    .then((response) => {
        resolve(response);
    })
    .catch((response) => {
        if(response.statusCode != null) {
            error(response);
        } else {
            error({ statusCode: 400, message: 'API call modApiMenu/getMenu failed' });
        }
        resolve(response);
    });
1
2
3
4
5
6
7
8
9
10
11
12
13

Bei vorhandenem statusCode wird in diesem Fall also die ~/components/error/400.vue Komponente eingebunden:

<!-- ~/components/error/400.vue -->
<template>
    <div class="container error-wrp">
        <i class="icon icon-frown" />
        <h1>Bad Request</h1>
        <div v-if="error.message != null" class="error-text" v-text="error.message" />
        <div v-else class="error-text" v-text="'The server was unable to process the request due to invalid syntax.'" />
    </div>
</template>
<!-- ... -->
1
2
3
4
5
6
7
8
9
10

Desweiteren existieren Fehler, die aufgrund von Benutzer Interaktionen mit z.B. Formularen entstehen können. Dafür gibt es in hubble zwei Varianten, um diese Fehler im Template darzustellen: Zum einen beinhalten Templates oft einen Block zur Darstellung eines errors Arrays und zum anderen gibt es die Möglichkeit, je nach Bedarf, eine sogenannte FlashMessage ( = Benachrichtigungen, die meist nach einer bestimmten Zeit wieder ausgeblendet werden) anzuzeigen.

Um die Inline Darstellungsvariante über das errors Array zu nutzen, müssen Fehlermeldungen, die anzuzeigen sind einem passenden Format entsprechen, um diesem Array hinzugefügt werden zu können.

<!-- as an example src: ~/components/customer/LoginForm.vue -->
<template v-for="error in errors">
    <div class="error-message" v-text="error" />
</template>
1
2
3
4
// ~/components/customer/LoginForm.vue
.catch(error => {
    this.errors.push(this.$t('Login failed'));

    // ...
});
1
2
3
4
5
6

Als Helferfunktionalität existiert außerdem das Mixin (opens new window) addBackendErrors (~/modules/@hubblecommerce/hubble/core/utils/formMixins.js), in die, bei Bedarf, eine Formatierung ausgelagert werden kann. Die Auslagerung in dieses Mixin eignet sich besonders gut, wenn es sich um die Anzeige von Fehlern handelt, die aus dem API Response stammen.

// ~/modules/@hubblecommerce/hubble/core/utils/formMixins.js
const addBackendErrors = {
    methods: {
        addBackendErrors: function(error) {
            // SW
            if(process.env.API_TYPE === 'sw') {
                if (!(error.errors === undefined)) {
                    return error.errors.map(val => val.detail);
                } else {
                    const errors = [];

                    errors.push(error);

                    return errors;
                }
            }
        },
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Dadurch ergibt sich also die Möglichkeit, dem errors Array auch die konkreten Fehlermeldungen aus dem API Response hinzuzufügen, wodurch sich folgender catch Block am Ende ergibt:

// ~/components/customer/LoginForm.vue 
.catch((error) => {
    this.errors.push(this.$t('Login failed'));

    _.forEach(this.addBackendErrors(error), error => {
        this.errors.push(error);
    })
});
1
2
3
4
5
6
7
8

Bei Fehlern, die nur eine einzige Nachricht anzeigen sollen, kann auch die oben erwähnte FlashMessage Komponente verwendet werden, die nach einer kurzen Zeit automatisch wieder ausgeblendet wird:

// ~/components/customer/CustomerAccountNavigation.vue
this.flashMessage({
    flashType: 'error',
    flashMessage: this.$t('Logout failed');
})
1
2
3
4
5

API Requests werden in der modApi/apiCall action durchgeführt und Fehler werden an die Caller action weitergereicht. Das Format des Rückgabewertes richtet sich dabei am Status Code aus. Es existieren folgende Formate, die als Rückgabewert auftreten können: error.response.data, error.request, error.message oder No network connection.