Skip to content

14. Voorbeeld [nuxt-11]: aanpassing van de laadafbeelding

Standaard is de laadafbeelding van [nuxt] een voortgangsbalk. Het voorbeeld [nuxt-11] laat zien dat deze kan worden vervangen door een eigen laadafbeelding:

Image

Het voorbeeld [nuxt-11] laat ook zien hoe je omgaat met laadfouten.

Image

Het voorbeeld [nuxt-11] is in eerste instantie verkregen door het voorbeeld [nuxt-10] te kopiëren:

Image

We gaan in [1] een plug-in voor de client toevoegen die tot taak heeft gebeurtenissen tussen componenten af te handelen.

14.1. De plug-in [event-bus]

De plug-in [event-bus] wordt zowel door de client als de server uitgevoerd, maar we zullen zien dat deze niet aan de serverzijde werkt. De code ervan is als volgt:


// er wordt een gebeurtenissenbus tussen de weergaven aangemaakt
import Vue from 'vue'
export default (context, inject) => {
  // de gebeurtenissenbus
  const eventBus = new Vue()
  // een functie [eventBus] in de context injecteren
  inject('eventBus', () => eventBus)
}
  • regel 5: de gebeurtenissenbus is een instantie van de klasse [Vue]. Deze beschikt namelijk over de methoden om gebeurtenissen te beheren:
    • [$emit]: om een gebeurtenis te genereren;
    • [$on]: om te luisteren naar een specifieke gebeurtenis;

Deze gebeurtenissenbus zal slechts één gebeurtenis beheren, [loading], die door de pagina’s zal worden gebruikt om de animatie die het wachten op het einde van een asynchrone functie weergeeft, te starten of te stoppen;

  • regel 7: we maken een functie [$eventBus] (1e argument) aan, die tot taak heeft het zojuist aangemaakte object [eventBus] (2e argument) terug te geven. Deze functie wordt in de context geïnjecteerd, zodat deze beschikbaar is in de objecten [context.app] en [this] van de pagina’s;

14.2. De lay-out [default.vue]

De lay-out [default.vue] verandert als volgt:


<template>
  <div class="container">
    <b-card>
      <!-- een bericht -->
      <b-alert show variant="success" align="center">
        <h4>[nuxt-11] : personnalisation de l'attente, gestion des erreurs</h4>
      </b-alert>
      <!-- het huidige overzicht van de routering -->
      <nuxt />
      <!-- wordt geladen -->
      <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>
      <!-- fout bij het laden -->
      <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
    }
  },
  // levenscyclus
  beforeCreate() {
    console.log('[default beforeCreate]')
  },
  created() {
    console.log('[default created]')
    // we luisteren naar de gebeurtenis [loading]
    this.$eventBus().$on('loading', this.mShowLoading)
    // evenals de gebeurtenis [errorLoadingMessage]
    this.$eventBus().$on('errorLoading', this.mShowErrorLoading)
  },
  beforeMount() {
    console.log('[default beforeMount]')
  },
  mounted() {
    console.log('[default mounted]')
  },
  methods: {
    // laadbeheer
    mShowLoading(value) {
      console.log('[default mShowLoading], showLoading=', value)
      this.showLoading = value
    },
    // laadfout
    mShowErrorLoading(value, errorLoadingMessage) {
      console.log('[default mShowErrorLoading], showErrorLoading=', value, 'errorLoadingMessage=', errorLoadingMessage)
      this.showErrorLoading = value
      this.errorLoadingMessage = errorLoadingMessage
    }
  }
}
</script>
  • regels 11-14: de wachtaanimatie. Deze wordt alleen weergegeven als de eigenschap [showLoading] waar is (regel 29);
  • regels 16-18: het foutbericht bij het laden. Dit wordt alleen weergegeven als de eigenschap [showErrorLoading] (regel 30) waar is;
  • regels 29-30: bij het eerste laden van de component worden zowel de wachtaanimatie als het foutbericht verborgen;
  • regels 37-43: zodra de pagina is aangemaakt, luistert deze naar de gebeurtenis [loading] (1e argument) op de door de plug-in aangemaakte gebeurtenissenbus. Bij ontvangst laat de pagina de methode [mShowLoading] van regels 52-55 (2e argument) uitvoeren;
  • regels 52-55: de waarde die door de methode [mShowLoading] wordt ontvangen, is een booleaanse waarde (true/false). Deze wordt gebruikt om het wachtbericht weer te geven of te verbergen;
  • regels 41-42: zodra de pagina wordt aangemaakt, luistert deze naar de gebeurtenis [errorLoading] (1e argument) op de gebeurtenissenbus die door de plug-in is aangemaakt. Bij ontvangst laat de pagina de methode [mShowErrorLoading] uit de regels 57-61 (2e argument) uitvoeren;
  • regel 57: de methode [mShowErrorLoading] ontvangt twee argumenten:
    • het eerste argument is een booleaanse waarde (true/false) om het foutbericht weer te geven of te verbergen;
    • het tweede argument is alleen aanwezig als er een fout is opgetreden. Het vertegenwoordigt de weer te geven foutmelding;
  • uit de logboekvermeldingen op regel 53 en 58 blijkt dat de methoden [showLoading] en [showErrorLoading] niet aan de serverzijde worden uitgevoerd;

14.3. De pagina [page1]

De code van de pagina [page1] verandert als volgt:


<!-- weergave nr. 1 -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigatie -->
    <Navigation slot="left" />
    <!-- bericht-->
    <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',
  // gebruikte componenten
  components: {
    Layout,
    Navigation
  },
  // asynchrone gegevens
  asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // begin wachttijd
    context.app.$eventBus().$emit('loading', true)
    // geen fout
    context.app.$eventBus().$emit('errorLoading', false)
    // een belofte wordt gedaan
    return new Promise(function(resolve, reject) {
      // een asynchrone functie wordt gesimuleerd
      setTimeout(function() {
        // einde wachten
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // het asynchrone resultaat wordt geretourneerd – hier een willekeurig getal
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
      }, 5000)
    })
  },

  // levenscyclus
  beforeCreate() {
    console.log('[page1 beforeCreate]')
  },
  created() {
    console.log('[page1 created]')
  },
  beforeMount() {
    console.log('[page1 beforeMount]')
  },
  mounted() {
    console.log('[page1 mounted]')
  }
}
</script>
  • de wijzigingen vinden plaats in de functie [asyncData] op de regels 26-47;
  • regels 29-30: voordat de asynchrone functie begint, wordt de gebeurtenis [loading] verzonden naar de andere pagina’s van de applicatie. Ter herinnering: in [asyncData] hebben we nog geen toegang tot het object [this], dat nog niet is aangemaakt. We gebruiken daarom de context die als argument wordt doorgegeven aan de functie [asyncData] (regel 26);
  • regel 30: de gebeurtenissenbus wordt gebruikt om aan te geven dat het laden gaat beginnen;
  • regel 38: de gebeurtenissenbus wordt gebruikt om aan te geven dat het laden is voltooid;

Opmerking: Tijdens de uitvoering, wanneer de pagina [page1] bij de server wordt opgevraagd, wordt de laadafbeelding niet weergegeven. In de logbestanden is te zien dat de methode [default.mShowLoading] aan de serverzijde niet wordt aangeroepen. Hoe dan ook heeft het geen zin om de laadafbeelding te zien wanneer de pagina bij de server wordt opgevraagd. De server stuurt de pagina pas naar de browser van de klant zodra de functie [asyncData] is voltooid. De laadafbeelding is dan overbodig. Dit geldt voor alle pagina’s van de applicatie die rechtstreeks bij de server worden opgevraagd.

14.4. De pagina [index]

De code van de pagina [index] is als volgt:


<!-- hoofdpagina -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigatie -->
    <Navigation slot="left" />
    <!-- bericht-->
    <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',
  // gebruikte componenten
  components: {
    Layout,
    Navigation
  },
  // asynchrone gegevens
  asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // begin wachttijd
    context.app.$eventBus().$emit('loading', true)
    // geen fout
    context.app.$eventBus().$emit('errorLoading', false)
    // een belofte wordt gedaan
    return new Promise(function(resolve, reject) {
      // een asynchrone functie wordt gesimuleerd
      setTimeout(function() {
        // einde wachten
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // er wordt een fout geretourneerd
        reject(new Error("le serveur n'a pas répondu assez vite"))
      }, 5000)
    }).catch((e) => context.error({ statusCode: 500, message: e.message }))
  },
  // levenscyclus
  beforeCreate() {
    console.log('[home beforeCreate]')
  },
  created() {
    console.log('[home created]')
  },
  beforeMount() {
    console.log('[home beforeMount]')
  },
  mounted() {
    console.log('[home mounted]')
    // geen fout
    this.$eventBus().$emit('errorLoading', false)
  }
}
</script>
  • regels 30-49: de functie [asyncData] is identiek aan die van de pagina [page1], op één detail na: op regel 46 wordt de asynchrone functie bij een fout beëindigd (gebruik van de methode [reject]);
  • regel 46: de parameter van de functie [reject] is een instantie van de klasse [Error]. De parameter van de constructor [Error] is het foutbericht;
  • regel 48: deze fout wordt opgevangen door de methode [catch] van [Promise], die de fout als parameter ontvangt. Vervolgens wordt de functie [context.error] gebruikt om de fout te melden. De parameter van de functie [context.error] is een object met in dit geval twee eigenschappen:
    • [statusCode]: een foutcode HTTP;
    • [message]: een foutmelding;

Of [asyncData] nu door de client of de server wordt uitgevoerd, in geval van een fout [context.error] geeft [nuxt] de pagina [layouts / error.vue] weer:

Image

Hoewel het om een pagina gaat, wordt de pagina [error.vue] gezocht in de map [layouts] (misschien om te voorkomen dat deze in de routes van de applicatie wordt opgenomen?). Hier is de pagina [error.vue] als volgt:


<!-- definitie HTML van de weergave -->
<template>
  <!-- pagina-indeling -->
  <Layout :left="true" :right="true">
    <!-- waarschuwing in de rechterkolom -->
    <template slot="right">
      <!-- bericht op gele achtergrond -->
      <b-alert show variant="danger" align="center">
        <h4>L'erreur suivante s'est produite : {{ JSON.stringify(error) }}</h4>
      </b-alert>
    </template>
    <!-- navigatiemenu in de linkerkolom -->
    <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',
  // gebruikte componenten
  components: {
    Layout,
    Navigation
  },
  // eigenschap [props]
  props: { error: { type: Object, default: () => 'waiting ...' } },
  // levenscyclus
  beforeCreate() {
    // client en server
    console.log('[error beforeCreate]')
  },
  created() {
    // client en server
    console.log('[error created, error=]', this.error)
  },
  beforeMount() {
    // alleen client
    console.log('[error beforeMount]')
  },
  mounted() {
    // alleen client
    console.log('[error mounted]')
  }
}
</script>

Wanneer [nuxt] de pagina [error.vue] weergeeft, draagt het de eigenschap [props], de fout die is opgetreden (regel 33), aan deze pagina over. Als de fout is veroorzaakt door [context.error(objet1)], krijgt de eigenschap [props] van de pagina [error.vue] de waarde [objet1]. In de documentatie van [nuxt] staat dat [objet1] ten minste de attributen van [statusCode, message] moet hebben. Regel 9 geeft de tekenreeks jSON weer van het ontvangen object [objet1].

14.5. De pagina [page2]

De pagina [page2] toont een andere manier om de fout af te handelen:

  • in [page1] wordt de fout weergegeven op een aparte pagina, [error.vue];
  • in [page2] wordt de fout weergegeven op de pagina [page2] die de fout heeft veroorzaakt;

De code van [page2] is als volgt:


<!-- weergave nr. 2 -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigatie -->
    <Navigation slot="left" />
    <!-- bericht -->
    <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',
  // gebruikte componenten
  components: {
    Layout,
    Navigation
  },
  // asynchrone gegevens
  asyncData(context) {
    // log
    console.log('[page2 asyncData started]')
    // begin wachttijd
    context.app.$eventBus().$emit('loading', true)
    // geen fout
    context.app.$eventBus().$emit('errorLoading', false)
    // een belofte wordt gedaan
    return new Promise(function(resolve, reject) {
      // een asynchrone functie wordt gesimuleerd
      setTimeout(function() {
        // einde wachten
        context.app.$eventBus().$emit('loading', false)
        // er wordt willekeurig een fout gegenereerd
        const errorLoadingMessage = "le serveur n'a pas répondu assez vite"
        // succesvol voltooid
        resolve({ showErrorLoading: true, errorLoadingMessage })
        // log
        console.log('[page2 asyncData finished]')
      }, 5000)
    })
  },
  // levenscyclus
  beforeCreate() {
    console.log('[page2 beforeCreate]')
  },
  created() {
    console.log('[page2 created]')
  },
  beforeMount() {
    console.log('[page2 beforeMount]')
  },
  mounted() {
    console.log('[page2 mounted]')
    // client
    if (this.showErrorLoading) {
      console.log('[page2 mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>

Opnieuw voegen we een functie [asyncData] toe aan de paginacode en net als bij [index] zal [page2] een fout genereren die we deze keer anders zullen afhandelen.

  • regel 44: zowel de server als de client sluiten de promise succesvol af door het resultaat [{ showErrorLoading: true, errorLoadingMessage }] terug te geven. We weten dat dit tot gevolg heeft dat de eigenschappen [showerrorLoading, errorLoadingMessage] worden opgenomen in de eigenschappen [data] van de pagina en dat de client deze eigenschappen zal ontvangen;
  • regels 60-67: we weten dat de functie [mounted] alleen door de client wordt uitgevoerd;
  • regel 63: de client controleert of de eigenschap [showErrorLoading] is ingesteld (door de server of de client, afhankelijk van het geval). Zo ja, dan genereert hij de gebeurtenis [‘errorLoading’] (regel 65) zodat de pagina [default] de foutmelding [this.errorLoadingMessage] weergeeft. Uiteindelijk verstuurt de server een pagina zonder dat er een foutmelding wordt weergegeven. Deze wordt op het laatste moment door de client weergegeven wanneer de pagina wordt ‘opgebouwd’;

14.6. Exécution

14.6.1. [nuxt.config]

Het uitvoerbestand [nuxt.config.js] ziet er als volgt uit:


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) {}
  },
  // broncodemap
  srcDir: 'nuxt-11',
  // router
  router: {
    // hoofdmap van de applicatie URL
    base: '/nuxt-11/'
  },
  // server
  server: {
    // servicepoort, standaard 3000
    port: 81,
    // netwerkadressen waarop wordt geluisterd, standaard localhost: 127.0.0.1
    // 0.0.0.0 = alle netwerkadressen van de machine
    host: 'localhost'
  }
}
  • regel 22: we stellen de eigenschap [loading] in op [false], zodat [nuxt] zijn standaard laadafbeelding niet gebruikt;
  • regel 31: de plug-in die de gebeurtenissenbus definieert;

14.6.2. L, een pagina [index] die door de server wordt uitgevoerd

Laten we de pagina [index] bij de server opvragen (we typen de URL [http://localhost:81/nuxt-11/] handmatig in). De pagina die door de clientbrowser wordt weergegeven, is de volgende:

Image

De logbestanden zien er als volgt uit:

Image

  • in [3] zien we dat de server de pagina [error.vue] verstuurt;
  • in [4] is te zien dat de client eveneens de pagina [error] weergeeft met dezelfde foutmelding als de server;
  • we kunnen opmerken dat de methode [mShowLoading] van de pagina [default] niet is aangeroepen aan de serverzijde, terwijl de pagina [index] een wachtrij had geactiveerd. Deze methode wordt aangeroepen bij ontvangst van een gebeurtenis en blijkbaar is de gebeurtenisafhandeling niet geïmplementeerd aan de serverzijde;

Laten we de broncode bekijken van de pagina die door de clientbrowser is ontvangen:


<!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>
  • regel 57: we zien dat de server een object [d] heeft verzonden, dat de fout weergeeft die aan de serverzijde is opgetreden;
  • regel 59: we zien een eigenschap [error] met als waarde het object [d]. We kunnen ons voorstellen dat het de aanwezigheid is van de eigenschap [error] in de door de server verzonden pagina die ervoor zorgt dat de clientscripts de pagina [error.vue] weergeven met de fout [error];

14.6.3. De pagina [page1] die door de server wordt uitgevoerd

We voeren handmatig URL [http://localhost:81/nuxt-11/page1] in. Na 5 seconden geeft de browser de volgende pagina weer:

Image

De weergegeven logbestanden zijn als volgt:

Image

  • in [1], de logbestanden van de server. We zien dat de methode [mShowLoading] van de pagina [default] niet is aangeroepen;
  • in [2], de logbestanden van de client;

14.6.4. De pagina [page2] die door de server wordt uitgevoerd

We voeren URL en [http://localhost:81/nuxt-11/page2] handmatig in. Na 5 seconden geeft de browser de volgende pagina weer:

Image

Laten we de logs bekijken die in de browser worden weergegeven:

Image

  • in [1], de logbestanden van de server. We herinneren eraan dat de server de eigenschappen [showErrorLoading, errorLoadingMessage] in de naar de clientbrowser verzonden pagina heeft opgenomen. We weten dat deze eigenschappen vervolgens worden geïntegreerd in de [data] van de door de client weergegeven pagina
  • in [3]: wanneer de pagina [page2] wordt geladen, vindt deze de eigenschap [showErrorLoading] op ‘waar’ staan. Vervolgens stuurt deze een gebeurtenis naar de pagina [default], zodat deze de door de server [4] verzonden foutmelding weergeeft;

14.6.5. De pagina [index] die door de client wordt uitgevoerd

We gebruiken nu de navigatielinks om de drie pagina’s weer te geven. Alle pagina’s die door de client worden weergegeven, zijn identiek aan die welke door de server worden weergegeven. Het enige verschil is dat telkens de laadafbeelding wordt weergegeven totdat de 5 seconden voorbij zijn.

We beginnen met de pagina [index]. De afbeelding die aangeeft dat er gewacht wordt tot het verstrijken van de 5 seconden, wordt dan weergegeven:

Image

en na 5 seconden verschijnt de volgende pagina:

Image

De uiteindelijke pagina is dus identiek aan die welke aan de serverzijde wordt weergegeven.

Image

Laten we nog eens kijken naar de functie [asyncData] van de pagina [index]:


asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // begin afwachten
    context.app.$eventBus().$emit('loading', true)
    // geen fout
    context.app.$eventBus().$emit('errorLoading', false)
    // er wordt een belofte gedaan
    return new Promise(function(resolve, reject) {
      // een asynchrone functie wordt gesimuleerd
      setTimeout(function() {
        // einde wachten
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // er wordt een fout geretourneerd
        reject(new Error("le serveur n'a pas répondu assez vite"))
      }, 5000)
    }).catch((e) => context.error({ statusCode: 500, message: e.message }))
}

De logbestanden van de client zijn als volgt:

Image

  • in [1] wordt de functie [asyncData] gestart;
  • in [2] wordt de wachtafbeelding gestart;
  • bij [2-3], zien we dat de pagina [default] de gebeurtenissen [loading, true], [2] en [errorLoading, false] heeft ontvangen, verzonden door de functie [asyncData] van de pagina [index] (regels 5 en 7);
  • in [4], einde van het wachten. De pagina [default] heeft de gebeurtenis [loading, false] ontvangen, verzonden door de pagina [index] (regel 13);
  • in [5] heeft de functie [asyncData] haar werk voltooid;
  • omdat de functie [asyncData] een fout heeft veroorzaakt met [context.error] (regel 19), wordt de pagina [error] weergegeven als [6];

14.6.6. De pagina [page1] wordt door de client uitgevoerd

Na 5 seconden te hebben gewacht, geeft de client de volgende pagina weer:

Image

Laten we de code van de functie [asyncData] uit [page1] nog eens bekijken:


asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // begin van het wachten
    context.app.$eventBus().$emit('loading', true)
    // geen fout
    context.app.$eventBus().$emit('errorLoading', false)
    // er wordt een belofte geretourneerd
    return new Promise(function(resolve, reject) {
      // een asynchrone functie wordt gesimuleerd
      setTimeout(function() {
        // einde wachten
        context.app.$eventBus().$emit('loading', false)
        // log
        console.log('[page1 asyncData finished]')
        // het asynchrone resultaat wordt geretourneerd – hier een willekeurig getal
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
      }, 5000)
    })
},

De logbestanden zien er als volgt uit:

Image

14.6.7. De pagina [page2] die door de client wordt uitgevoerd

Na 5 seconden wachten geeft de client de volgende pagina weer:

Image

Laten we nog eens kijken naar de code van de functies [asyncData] en [mounted] uit [page2]:


asyncData(context) {
    // log
    console.log('[page2 asyncData started]')
    // begin wachten
    context.app.$eventBus().$emit('loading', true)
    // geen fout
    context.app.$eventBus().$emit('errorLoading', false)
    // we geven een belofte af
    return new Promise(function(resolve, reject) {
      // we simuleren een asynchrone functie
      setTimeout(function() {
        // einde wachten
        context.app.$eventBus().$emit('loading', false)
        // er wordt willekeurig een fout gegenereerd
        const errorLoadingMessage = "le serveur n'a pas répondu assez vite"
        // succesvol voltooid
        resolve({ showErrorLoading: true, errorLoadingMessage })
        // log
        console.log('[page2 asyncData finished]')
      }, 5000)
    })
  }

mounted() {
    console.log('[page2 mounted]')
    // client
    if (this.showErrorLoading) {
      console.log('[page2 mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
}

De logbestanden zien er als volgt uit:

Image

  • in [1] heeft de pagina [default] de gebeurtenis [showErrorLoading, true] ontvangen, verzonden door [page2] (regel 29), waarin wordt gevraagd om de foutmelding weer te geven;