Skip to content

14. Beispiel [nuxt-11]: Anpassen des Ladebildes

Standardmäßig ist das [nuxt]-Ladebild ein Fortschrittsbalken. Beispiel [nuxt-11] zeigt, dass Sie es durch Ihr eigenes Ladebild ersetzen können:

Image

Das [nuxt-11]-Beispiel zeigt auch, wie man mit Ladefehlern umgeht.

Image

Das [nuxt-11]-Beispiel basiert ursprünglich auf dem [nuxt-10]-Beispiel:

Image

In [1] fügen wir ein Plugin für den Client hinzu, das für die Verwaltung von Ereignissen zwischen Komponenten zuständig ist.

14.1. Das [event-bus]-Plugin

Das [event-bus]-Plugin wird sowohl vom Client als auch vom Server ausgeführt, aber wir werden sehen, dass es auf der Serverseite nicht funktioniert. Sein Code lautet wie folgt:


// on crée un bus d'événements entre les vues
import Vue from 'vue'
export default (context, inject) => {
  // le bus d'événements
  const eventBus = new Vue()
  // injection d'une fonction [eventBus] dans le contexte
  inject('eventBus', () => eventBus)
}
  • Zeile 5: Der Event-Bus ist eine Instanz der Klasse [Vue]. Diese Klasse stellt Methoden zur Verarbeitung von Ereignissen bereit:
    • [$emit]: zum Auslösen eines Ereignisses;
    • [$on]: um auf ein bestimmtes Ereignis zu warten;

Dieser Event-Bus verarbeitet nur ein einziges Ereignis, [loading], das von Seiten verwendet wird, um die Ladeanimation zu starten/zu stoppen, während auf den Abschluss einer asynchronen Funktion gewartet wird;

  • Zeile 7: Wir erstellen eine Funktion [$eventBus] (erstes Argument), deren Aufgabe es ist, das soeben erstellte [eventBus]-Objekt (zweites Argument) zurückzugeben. Diese Funktion wird in den Kontext injiziert, sodass sie in den Objekten [context.app] und [this] der Seiten verfügbar ist;

14.2. Das Layout [default.vue]

Das Layout [default.vue] entwickelt sich wie folgt:


<template>
  <div class="container">
    <b-card>
      <!-- un message -->
      <b-alert show variant="success" align="center">
        <h4>[nuxt-11] : personnalisation de l'attente, gestion des erreurs</h4>
      </b-alert>
      <!-- la vue courante du routage -->
      <nuxt />
      <!-- loading -->
      <b-alert v-if="showLoading" show variant="light">
        <strong>Requête au serveur de données en cours...</strong>
        <div class="spinner-border ml-auto" role="status" aria-hidden="true"></div>
      </b-alert>
      <!-- erreur de chargement -->
      <b-alert v-if="showErrorLoading" show variant="danger">
        <strong>La requête au serveur de données a échoué : {{ errorLoadingMessage }}</strong>
      </b-alert>
    </b-card>
  </div>
</template>
 
<script>
/* eslint-disable no-console */
export default {
  name: 'App',
  data() {
    return {
      showLoading: false,
      showErrorLoading: false
    }
  },
  // life cycle
  beforeCreate() {
    console.log('[default beforeCreate]')
  },
  created() {
    console.log('[default created]')
    // listen to the evt [loading]
    this.$eventBus().$on('loading', this.mShowLoading)
    // and the [errorLoadingMessage] event
    this.$eventBus().$on('errorLoading', this.mShowErrorLoading)
  },
  beforeMount() {
    console.log('[default beforeMount]')
  },
  mounted() {
    console.log('[default mounted]')
  },
  methods: {
    // load management
    mShowLoading(value) {
      console.log('[default mShowLoading], showLoading=', value)
      this.showLoading = value
    },
    // loading error
    mShowErrorLoading(value, errorLoadingMessage) {
      console.log('[default mShowErrorLoading], showErrorLoading=', value, 'errorLoadingMessage=', errorLoadingMessage)
      this.showErrorLoading = value
      this.errorLoadingMessage = errorLoadingMessage
    }
  }
}
</script>
  • Zeilen 11–14: die Ladeanimation. Sie wird nur angezeigt, wenn die Eigenschaft [showLoading] auf „true“ gesetzt ist (Zeile 29);
  • Zeilen 16–18: Die Ladefehlermeldung. Sie wird nur angezeigt, wenn die Eigenschaft [showErrorLoading] (Zeile 30) auf „true“ gesetzt ist;
  • Zeilen 29–30: Beim ersten Laden der Komponente werden sowohl die Ladeanimation als auch die Fehlermeldung ausgeblendet;
  • Zeilen 37–43: Nach der Erstellung überwacht die Seite das [loading]-Ereignis (erstes Argument) auf dem vom Plugin erstellten Ereignisbus. Nach dessen Empfang führt sie die Methode [mShowLoading] in den Zeilen 52–55 (zweites Argument) aus;
  • Zeilen 52–55: Der von der Methode [mShowLoading] empfangene Wert ist ein Boolescher Wert (true/false). Er wird verwendet, um die Lademeldung ein- oder auszublenden;
  • Zeilen 41–42: Beim Erstellen der Seite wird auf das Ereignis [errorLoading] (erstes Argument) auf dem vom Plugin erstellten Ereignisbus gewartet. Nach dem Empfang wird die Methode [mShowErrorLoading] in den Zeilen 57–61 (zweites Argument) ausgeführt;
  • Zeile 57: Die Methode [mShowErrorLoading] nimmt zwei Argumente entgegen:
    • Das erste Argument ist ein Boolescher Wert (true/false), um die Fehlermeldung anzuzeigen oder auszublenden;
    • das zweite Argument ist nur vorhanden, wenn ein Fehler aufgetreten ist. Es stellt die anzuzeigende Fehlermeldung dar;
  • Die Logs in den Zeilen 53 und 58 zeigen uns, dass die Methoden [showLoading] und [showErrorLoading] nicht auf der Serverseite ausgeführt werden;

14.3. Die Seite [page1]

Der Code für die Seite [page1] ändert sich wie folgt:


<!-- vue n° 1 -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigation -->
    <Navigation slot="left" />
    <!-- message-->
    <b-alert slot="right" show variant="primary"> Page 1 -- result={{ result }} </b-alert>
  </Layout>
</template>
 
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
 
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
 
export default {
  name: 'Page1',
  // components used
  components: {
    Layout,
    Navigation
  },
  // asynchronous data
  asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // start waiting
    context.app.$eventBus().$emit('loading', true)
    // no error
    context.app.$eventBus().$emit('errorLoading', false)
    // we make a promise
    return new Promise(function(resolve, reject) {
      // we simulate an asynchronous function
      setTimeout(function() {
        // end waiting
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // we make the result asynchronous - a random number here
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
      }, 5000)
    })
  },
 
  // life cycle
  beforeCreate() {
    console.log('[page1 beforeCreate]')
  },
  created() {
    console.log('[page1 created]')
  },
  beforeMount() {
    console.log('[page1 beforeMount]')
  },
  mounted() {
    console.log('[page1 mounted]')
  }
}
</script>
  • Die Änderungen finden in der Funktion [asyncData] in den Zeilen 26–47 statt;
  • Zeilen 29–30: Bevor die asynchrone Funktion beginnt, wird das [loading]-Ereignis an die anderen Seiten der Anwendung gesendet. Beachten Sie, dass wir in [asyncData] noch keinen Zugriff auf das [this]-Objekt haben, da dieses noch nicht erstellt wurde. Wir verwenden daher den Kontext, der als Argument an die [asyncData]-Funktion übergeben wird (Zeile 26);
  • Zeile 30: Der Ereignisbus wird verwendet, um anzuzeigen, dass der Ladevorgang bald beginnt;
  • Zeile 38: Wir verwenden den Ereignisbus, um anzuzeigen, dass der Ladevorgang abgeschlossen ist;

Hinweis: Zur Laufzeit wird das Lade-Bild nicht angezeigt, wenn die Seite [page1] vom Server angefordert wird. In den Protokollen sehen wir, dass auf der Serverseite die Methode [default.mShowLoading] nicht aufgerufen wird. In jedem Fall macht es keinen Sinn, das Lade-Bild zu sehen, wenn die Seite vom Server angefordert wird. Der Server sendet die Seite erst dann an den Browser des Clients, wenn die Funktion [asyncData] beendet ist. Das Lade-Bild ist daher überflüssig. Dies gilt für alle Seiten der Anwendung, die direkt vom Server angefordert werden.

14.4. Die Seite [index]

Der Code für die [index]-Seite lautet wie folgt:


<!-- page principale -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigation -->
    <Navigation slot="left" />
    <!-- message-->
    <b-alert slot="right" show variant="warning">
      Home
    </b-alert>
  </Layout>
</template>
 
<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */
/* eslint-disable nuxt/no-timing-in-fetch-data */
 
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
 
export default {
  name: 'Home',
  // components used
  components: {
    Layout,
    Navigation
  },
  // asynchronous data
  asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // start waiting
    context.app.$eventBus().$emit('loading', true)
    // no error
    context.app.$eventBus().$emit('errorLoading', false)
    // we make a promise
    return new Promise(function(resolve, reject) {
      // we simulate an asynchronous function
      setTimeout(function() {
        // end waiting
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // we return an error
        reject(new Error("le serveur n'a pas répondu assez vite"))
      }, 5000)
    }).catch((e) => context.error({ statusCode: 500, message: e.message }))
  },
  // life cycle
  beforeCreate() {
    console.log('[home beforeCreate]')
  },
  created() {
    console.log('[home created]')
  },
  beforeMount() {
    console.log('[home beforeMount]')
  },
  mounted() {
    console.log('[home mounted]')
    // no error
    this.$eventBus().$emit('errorLoading', false)
  }
}
</script>
  • Zeilen 30–49: Die Funktion [asyncData] ist identisch mit der auf der Seite [page1], mit einer Ausnahme: In Zeile 46 wird die asynchrone Funktion bei einem Fehler abgebrochen (mithilfe der Methode [reject]);
  • Zeile 46: Der Parameter der Funktion [reject] ist eine Instanz der Klasse [Error]. Der Parameter des Konstruktors [Error] ist die Fehlermeldung;
  • Zeile 48: Dieser Fehler wird von der [catch]-Methode des [Promise] abgefangen, die den Fehler als Parameter erhält. Anschließend verwenden wir die Funktion [context.error], um den Fehler zu melden. Der Parameter der Funktion [context.error] ist hier ein Objekt mit zwei Eigenschaften:
    • [statusCode]: ein HTTP-Fehlercode;
    • [message]: eine Fehlermeldung;

Unabhängig davon, ob [asyncData] vom Client oder vom Server ausgeführt wird, zeigt [nuxt] im Falle eines [context.error] die Seite [layouts/error.vue] an:

Image

Obwohl es sich um eine Seite handelt, wird die Seite [error.vue] im Ordner [layouts] gesucht (vielleicht, um zu verhindern, dass sie in die Routen der Anwendung aufgenommen wird?). Hier sieht die Seite [error.vue] wie folgt aus:


<!-- définition HTML de la vue -->
<template>
  <!-- mise en page -->
  <Layout :left="true" :right="true">
    <!-- alerte dans la colonne de droite -->
    <template slot="right">
      <!-- message sur fond jaune -->
      <b-alert show variant="danger" align="center">
        <h4>L'erreur suivante s'est produite : {{ JSON.stringify(error) }}</h4>
      </b-alert>
    </template>
    <!-- menu de navigation dans la colonne de gauche -->
    <Navigation slot="left" />
  </Layout>
</template>
 
<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */
 
import Layout from '@/components/layout'
import Navigation from '@/components/navigation'
 
export default {
  name: 'Error',
  // components used
  components: {
    Layout,
    Navigation
  },
  // property [props]
  props: { error: { type: Object, default: () => 'waiting ...' } },
  // life cycle
  beforeCreate() {
    // client and server
    console.log('[error beforeCreate]')
  },
  created() {
    // client and server
    console.log('[error created, error=]', this.error)
  },
  beforeMount() {
    // customer only
    console.log('[error beforeMount]')
  },
  mounted() {
    // customer only
    console.log('[error mounted]')
  }
}
</script>

Wenn [nuxt] die Seite [error.vue] rendert, übergibt es den aufgetretenen Fehler als [props]-Eigenschaft (Zeile 33). Wenn der Fehler durch [context.error(object1)] verursacht wurde, hat die [props]-Eigenschaft der Seite [error.vue] den Wert [object1]. In der [nuxt]-Dokumentation heißt es, dass [object1] mindestens die Attribute [statusCode, message] haben muss. In Zeile 9 wird die JSON-Zeichenkette des empfangenen [object1]-Objekts angezeigt.

14.5. Die Seite [page2]

Die Seite [page2] zeigt eine weitere Möglichkeit, den Fehler zu behandeln:

  • auf [page1] wird der Fehler auf einer separaten Seite [error.vue] angezeigt;
  • auf [page2] wird der Fehler auf der Seite [page2] angezeigt, die den Fehler verursacht hat;

Der Code für [Seite2] lautet wie folgt:


<!-- vue n° 2 -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigation -->
    <Navigation slot="left" />
    <!-- message -->
    <b-alert slot="right" show variant="secondary">
      Page 2
    </b-alert>
  </Layout>
</template>
 
<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */
 
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
 
export default {
  name: 'Page2',
  // components used
  components: {
    Layout,
    Navigation
  },
  // asynchronous data
  asyncData(context) {
    // log
    console.log('[page2 asyncData started]')
    // start waiting
    context.app.$eventBus().$emit('loading', true)
    // no error
    context.app.$eventBus().$emit('errorLoading', false)
    // we make a promise
    return new Promise(function(resolve, reject) {
      // we simulate an asynchronous function
      setTimeout(function() {
        // end waiting
        context.app.$eventBus().$emit('loading', false)
        // arbitrarily generate an error
        const errorLoadingMessage = "le serveur n'a pas répondu assez vite"
        // successful completion
        resolve({ showErrorLoading: true, errorLoadingMessage })
        // log
        console.log('[page2 asyncData finished]')
      }, 5000)
    })
  },
  // life cycle
  beforeCreate() {
    console.log('[page2 beforeCreate]')
  },
  created() {
    console.log('[page2 created]')
  },
  beforeMount() {
    console.log('[page2 beforeMount]')
  },
  mounted() {
    console.log('[page2 mounted]')
    // customer
    if (this.showErrorLoading) {
      console.log('[page2 mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>

Erneut fügen wir eine [asyncData]-Funktion in den Seitencode ein, und genau wie bei [index] wird [page2] einen Fehler generieren, den wir dieses Mal anders behandeln werden.

  • Zeile 44: Sowohl der Server als auch der Client lösen das Promise erfolgreich auf, indem sie das Ergebnis [{ showErrorLoading: true, errorLoadingMessage }] zurückgeben. Wir wissen, dass dadurch die Eigenschaften [showErrorLoading, errorLoadingMessage] in die [data]-Eigenschaften der Seite aufgenommen werden und dass der Client diese Eigenschaften erhält;
  • Zeilen 60–67: Wir wissen, dass die Funktion [mounted] nur vom Client ausgeführt wird;
  • Zeile 63: Der Client prüft, ob die Eigenschaft [showErrorLoading] gesetzt wurde (je nach Fall durch den Server oder den Client). Ist dies der Fall, löst er das Ereignis [‘errorLoading’] aus (Zeile 65), sodass die [default]-Seite die Fehlermeldung [this.errorLoadingMessage] anzeigt. Letztendlich sendet der Server eine Seite, auf der keine Fehlermeldung angezeigt wird. Die Fehlermeldung wird im letzten Moment vom Client angezeigt, wenn die Seite „gemountet“ wird;

14.6. Ausführung

14.6.1. [nuxt.config]

Die Laufzeitdatei [nuxt.config.js] sieht wie folgt aus:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: 'Introduction à [nuxt.js]',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: 'ssr routing loading asyncdata middleware plugins store'
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: false,
 
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [{ src: '@/plugins/event-bus' }],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  },
  // source code directory
  srcDir: 'nuxt-11',
  // router
  router: {
    // application URL root
    base: '/nuxt-11/'
  },
  // server
  server: {
    // service port, default 3000
    port: 81,
    // network addresses listened to, default localhost: 127.0.0.1
    // 0.0.0.0 = all the machine's network addresses
    host: 'localhost'
  }
}
  • Zeile 22: Setze die Eigenschaft [loading] auf [false], damit [nuxt] nicht sein Standard-Ladebild verwendet;
  • Zeile 31: das Plugin, das den Event-Bus definiert;

14.6.2. Die vom Server bereitgestellte [index]-Seite

Rufen wir die [index]-Seite vom Server ab (wir geben die URL [http://localhost:81/nuxt-11/] manuell ein). Die vom Browser des Clients angezeigte Seite sieht wie folgt aus:

Image

Die Protokolle sehen wie folgt aus:

Image

  • In [3] sehen wir, dass der Server die Seite [error.vue] sendet;
  • In [4] sehen wir, dass der Client ebenfalls die Seite [error] mit demselben Fehler wie der Server anzeigt;
  • Wir können sehen, dass die Methode [mShowLoading] der Seite [default] auf der Serverseite nicht aufgerufen wurde, obwohl die Seite [index] eine Wartezeit ausgelöst hatte. Diese Methode wird beim Empfang eines Ereignisses aufgerufen, und offensichtlich ist die Ereignisbehandlung auf der Serverseite nicht implementiert;

Sehen wir uns den Quellcode der Seite an, die der Browser des Clients empfangen hat:


<!doctype html>
<html data-n-head-ssr>
<head>
  <title>Introduction à [nuxt.js]</title>
  <meta data-n-head="ssr" charset="utf-8">
  <meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
  <meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
  <link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
  <base href="/nuxt-11/">
  <link rel="preload" href="/nuxt-11/_nuxt/runtime.js" as="script">
  <link rel="preload" href="/nuxt-11/_nuxt/commons.app.js" as="script">
  <link rel="preload" href="/nuxt-11/_nuxt/vendors.app.js" as="script">
  <link rel="preload" href="/nuxt-11/_nuxt/app.js" as="script">
  ...
</head>
<body>
  <div data-server-rendered="true" id="__nuxt">
    <div id="__layout">
      <div class="container">
        <div class="card">
          <div class="card-body">
            <div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
            <h4>[nuxt-11] : personnalisation de l'attente, gestion des erreurs</h4>
              </div>
            <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-11/" target="_self" class="nav-link active nuxt-link-active">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-11/page1" target="_self" class="nav-link">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-11/page2" target="_self" class="nav-link">
                        Page 2
                      </a>
                    </li>
                  </ul>
                </div> <div class="col-10"><div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-danger">
                <h4>L'erreur suivante s'est produite : {&quot;statusCode&quot;:500,&quot;message&quot;:&quot;le serveur n'a pas répondu assez vite&quot;}</h4>
                    </div>
                </div>
              </div>
            </div>  
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>window.__NUXT__ = (function (a, b, c, d) {
  d.statusCode = 500; d.message = "le serveur n'a pas répondu assez vite";
  return {
    layout: "default", data: [d], error: d, serverRendered: true,
    logs: [
      { date: new Date(1575047424168), args: ["[event-bus créé]"], type: a, level: b, tag: c },
      { date: new Date(1575047424175), args: ["[page1 asyncData started]"], type: a, level: b, tag: c },
      { date: new Date(1575047429455), args: ["[page1 asyncData finished]"], type: a, level: b, tag: c },
      { date: new Date(1575047429515), args: ["[default beforeCreate]"], type: a, level: b, tag: c },
      { date: new Date(1575047429675), args: ["[default created]"], type: a, level: b, tag: c },
      { date: new Date(1575047430157), args: ["[error beforeCreate]"], type: a, level: b, tag: c },
      { date: new Date(1575047430246), args: ["[error created, error=]", "{ statusCode: 500,\n  message: 'le serveur n\\'a pas répondu assez vite' }"], type: a, level: b, tag: c }]
  }
    }("log", 2, "", {}));</script>
  <script src="/nuxt-11/_nuxt/runtime.js" defer></script>
  <script src="/nuxt-11/_nuxt/commons.app.js" defer></script>
  <script src="/nuxt-11/_nuxt/vendors.app.js" defer></script>
  <script src="/nuxt-11/_nuxt/app.js" defer></script>
</body>
</html>
  • Zeile 57: Wir sehen, dass der Server ein Objekt [d] gesendet hat, das den auf der Serverseite aufgetretenen Fehler darstellt;
  • Zeile 59: Wir sehen eine Eigenschaft [error], deren Wert das Objekt [d] ist. Wir können davon ausgehen, dass das Vorhandensein der Eigenschaft [error] in der vom Server gesendeten Seite dazu führt, dass die clientseitigen Skripte die Seite [error.vue] mit dem Fehler [error] anzeigen;

14.6.3. Die vom Server ausgeführte Seite [page1]

Wir geben die URL [http://localhost:81/nuxt-11/page1] manuell ein. Nach 5 Sekunden zeigt der Browser die folgende Seite an:

Image

Die angezeigten Protokolle lauten wie folgt:

Image

  • in [1] die Serverprotokolle. Beachten Sie, dass die Methode [mShowLoading] der Seite [default] nicht aufgerufen wurde;
  • in [2] die Client-Protokolle;

14.6.4. Die vom Server ausgeführte Seite [page2]

Wir geben die URL [http://localhost:81/nuxt-11/page2] manuell ein. Nach 5 Sekunden zeigt der Browser die folgende Seite an:

Image

Sehen wir uns die im Browser angezeigten Protokolle an:

Image

  • in [1] die Serverprotokolle. Erinnern wir uns daran, dass der Server die Eigenschaften [showErrorLoading, errorLoadingMessage] in die an den Client-Browser gesendete Seite aufgenommen hat. Wir wissen, dass diese Eigenschaften dann in den [data] der vom Client angezeigten Seite aufgenommen werden
  • in [3] findet die Seite [page2] beim Laden die Eigenschaft [showErrorLoading] mit dem Wert „true“. Sie sendet daraufhin ein Ereignis an die Seite [default], damit diese die vom Server gesendete Fehlermeldung anzeigt [4];

14.6.5. Die vom Client ausgeführte Seite [index]

Wir verwenden nun die Navigationslinks, um die drei Seiten anzuzeigen. Alle vom Client angezeigten Seiten sind identisch mit denen, die vom Server angezeigt werden. Der einzige Unterschied besteht darin, dass jedes Mal das 5-Sekunden-Ladebild angezeigt wird.

Wir beginnen mit der Seite [index]. Das Lade-Bild wird dann angezeigt:

Image

und nach 5 Sekunden erscheint die folgende Seite:

Image

Die endgültige Seite ist daher identisch mit der auf der Serverseite angezeigten.

Image

Erinnern Sie sich an die Funktion [asyncData] auf der Seite [index]:


asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // start waiting
    context.app.$eventBus().$emit('loading', true)
    // no error
    context.app.$eventBus().$emit('errorLoading', false)
    // we make a promise
    return new Promise(function(resolve, reject) {
      // we simulate an asynchronous function
      setTimeout(function() {
        // end waiting
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // we return an error
        reject(new Error("le serveur n'a pas répondu assez vite"))
      }, 5000)
    }).catch((e) => context.error({ statusCode: 500, message: e.message }))
}

Die Client-Protokolle lauten wie folgt:

Image

  • in [1] wird die Funktion [asyncData] gestartet;
  • in [2] wird das Lade-Bild angezeigt;
  • in [2-3] sehen wir, dass die Seite [default] die von der Funktion [asyncData] der Seite [index] gesendeten Ereignisse [loading, true] [2] und [errorLoading, false] empfangen hat (Zeilen 5 und 7);
  • in [4] endet die Wartezeit. Die Seite [default] hat das von der Seite [index] gesendete Ereignis [loading, false] empfangen (Zeile 13);
  • In [5] hat die Funktion [asyncData] ihre Arbeit beendet;
  • Da die Funktion [asyncData] einen Fehler mit [context.error] erzeugt hat (Zeile 19), wird die Seite [error] angezeigt [6];

14.6.6. Die vom Client ausgeführte Seite [page1]

Nach einer Wartezeit von 5 Sekunden zeigt der Client die folgende Seite an:

Image

Sehen wir uns den Code für die Funktion [asyncData] aus [page1] an:


asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // start waiting
    context.app.$eventBus().$emit('loading', true)
    // no error
    context.app.$eventBus().$emit('errorLoading', false)
    // we make a promise
    return new Promise(function(resolve, reject) {
      // we simulate an asynchronous function
      setTimeout(function() {
        // end waiting
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // we make the result asynchronous - a random number here
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
      }, 5000)
    })
},

Die Protokolle lauten wie folgt:

Image

14.6.7. Die vom Client ausgeführte Seite [page2]

Nach einer Wartezeit von 5 Sekunden zeigt der Client die folgende Seite an:

Image

Sehen wir uns den Code für die Funktionen [asyncData] und [mounted] in [page2] an:


asyncData(context) {
    // log
    console.log('[page2 asyncData started]')
    // start waiting
    context.app.$eventBus().$emit('loading', true)
    // no error
    context.app.$eventBus().$emit('errorLoading', false)
    // we make a promise
    return new Promise(function(resolve, reject) {
      // we simulate an asynchronous function
      setTimeout(function() {
        // end waiting
        context.app.$eventBus().$emit('loading', false)
        // arbitrarily generate an error
        const errorLoadingMessage = "le serveur n'a pas répondu assez vite"
        // successful completion
        resolve({ showErrorLoading: true, errorLoadingMessage })
        // log
        console.log('[page2 asyncData finished]')
      }, 5000)
    })
  }
 
mounted() {
    console.log('[page2 mounted]')
    // customer
    if (this.showErrorLoading) {
      console.log('[page2 mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
}

Die Protokolle lauten wie folgt:

Image

  • In [1] empfing die [default]-Seite das von [page2] gesendete Ereignis [showErrorLoading, true] (Zeile 29), das sie anweist, die Fehlermeldung anzuzeigen;