15. Beispiel [nuxt-12]: HTTP-Anfragen mit axios
15.1. Einführung
In diesem neuen Beispiel werden wir untersuchen, wie man HTTP-Anfragen mithilfe der [axios]-Bibliothek innerhalb von [asyncData]-Funktionen stellt. Außerdem werden wir bereits behandelte Konzepte anwenden:
- die Verwendung von Plugins aus dem Beispiel [nuxt-06]:
- das Speichern des Stores in einem Session-Cookie aus dem Beispiel [nuxt-06];
- Navigationssteuerung mithilfe von Middleware aus dem Beispiel [nuxt-09];
- Fehlerbehandlung aus dem Beispiel [nuxt-11];
Die Architektur des Beispiels sieht wie folgt aus:

- Die [nuxt]-Anwendung wird auf dem [node.js]-Server [3] gehostet, vom Browser [1] heruntergeladen und anschließend von diesem ausgeführt;
- sowohl der [nuxt]-Client [1] als auch der [nuxt]-Server [3] senden HTTP-Anfragen an den Datenserver [2]. Dieser Server ist der im Abschnitt zu PHP 7 entwickelte Steuerberechnungsserver. Wir verwenden dessen neueste Version, Version 14, mit aktivierten CORS-Anfragen;
Die Architektur des Beispiels lässt sich wie folgt vereinfacht darstellen:

- In [1] liefert der [Node.js]-Server die [Nuxt]-Seiten an den Browser [2]. Es ist die [Web]-Schicht [8] des Servers, die diese Seiten bereitstellt. Um die Seite bereitzustellen, hat der Server möglicherweise externe Daten vom Datenserver [3] angefordert. Es ist die [DAO]-Schicht [9], die die erforderlichen HTTP-Anfragen stellt;
- Bei jeder Seitenanfrage an den [Node.js]-Server [1] erhält der Browser [2] die gesamte [Nuxt]-Anwendung, die dann im SPA-Modus ausgeführt wird. Der [UI]-Block (User Interface) [4] zeigt dem Benutzer [Vue.js]-Seiten an. Die Aktionen des Benutzers oder der natürliche Lebenszyklus der Seiten können Anfragen nach externen Daten vom Datenserver [3] auslösen. Die [DAO]-Schicht [5] führt dann die erforderlichen HTTP-Anfragen durch;
15.2. Projektverzeichnisstruktur

15.3. Die Konfigurationsdatei [nuxt.config.js]
Das Projekt wird über die folgende [nuxt.config.js]-Datei gesteuert:
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/client/plgSession', mode: 'client' },
{ src: '@/plugins/server/plgSession', mode: 'server' },
{ src: '@/plugins/client/plgDao', mode: 'client' },
{ src: '@/plugins/server/plgDao', mode: 'server' },
{ src: '@/plugins/client/plgEventBus', mode: 'client' }
],
/*
** 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',
// https://www.npmjs.com/package/cookie-universal-nuxt
'cookie-universal-nuxt'
],
/*
** 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-12',
// router
router: {
// application URL root
base: '/nuxt-12/',
// routing middleware
middleware: ['routing']
},
// 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'
},
// environment
env: {
// axios configuration
timeout: 2000,
withCredentials: true,
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
// session cookie configuration [nuxt]
maxAge: 60 * 5
}
}
- Zeile 22: Wir kümmern uns selbst um die Benachrichtigung über den Abschluss einer asynchronen Aktion;
- Zeile 31: Wir werden verschiedene Plugins verwenden, die entweder für den Client oder für den Server spezialisiert sind, aber nicht für beides gleichzeitig;
- Zeile 52: Das [axios]-Modul ist in [nuxt] integriert. Dadurch steht das [axios]-Objekt, das HTTP-Anfragen von der [nuxt]-Anwendung an den PHP-Steuerberechnungsserver verarbeitet, in [context.$axios] zur Verfügung;
- Zeile 54: Das Modul [cookie-universal-nuxt] ermöglicht es uns, die [nuxt]-Sitzung in einem Cookie zu speichern;
- Zeile 60: Die Eigenschaft [axios] ermöglicht es uns, das Modul [@nuxtjs/axios] aus Zeile 52 zu konfigurieren. Wir werden diese Option nicht verwenden, sondern bevorzugen stattdessen die Eigenschaft [env] aus Zeile 88;
- Zeile 90: Maximale Wartezeit für eine Antwort vom Steuerberechnungsserver;
- Zeile 91: erforderlich für den [nuxt]-Client – ermöglicht die Verwendung von Cookies bei der Kommunikation mit dem Steuerberechnungsserver;
- Zeile 92: Die Basis-URL des Steuerberechnungsservers;
- Zeile 94: Lebensdauer der Nuxt-Sitzung (5 Min.);
- Zeile 77: Die Navigation des Clients und des [nuxt]-Servers wird durch Routing-Middleware gesteuert;
15.4. Die [UI]-Ebene der Anwendung

Wir werden der [nuxt]-Anwendung über die folgende Ansicht Zugriff auf die API des Steuerberechnungsservers gewähren:

- in [2], das Menü, das den Zugriff auf die API des Steuerberechnungsservers ermöglicht:
- [Authentication]: entspricht der Seite [authentication]. Diese Seite sendet eine Authentifizierungsanfrage an den Steuerberechnungsserver unter Verwendung der Anmeldedaten [admin, admin], die derzeit die einzigen autorisierten sind. Das angezeigte Ergebnis ähnelt [3];
- [AdminData-Anfrage]: entspricht der Seite [get-admindata]. Diese Seite fordert Daten vom Steuerberechnungsserver an – hier als [adminData] bezeichnet –, die die Steuerberechnung ermöglichen. Das angezeigte Ergebnis ähnelt [3];
- [End Tax Session]: entspricht der Seite [end-session]. Diese Seite sendet eine PHP-Anfrage zum Beenden der Sitzung an den Steuerberechnungsserver. Der Server bricht daraufhin die aktuelle PHP-Sitzung ab und initialisiert eine neue, leere Sitzung;
15.5. Die [dao]-Schichten der [nuxt]-Anwendung
Wie oben erwähnt, wird die Architektur der [nuxt]-Anwendung wie folgt aussehen:

- In [1] liefert der [node.js]-Server die [nuxt]-Seiten an den Browser [2]. Es ist die [Web]-Schicht [8] des Servers, die diese Seiten bereitstellt. Um die Seite bereitzustellen, hat der Server möglicherweise externe Daten vom Datenserver [3] angefordert. Es ist die [DAO]-Schicht [9], die die erforderlichen HTTP-Anfragen stellt;
- Bei jeder Seitenanfrage an den [Node.js]-Server [1] erhält der Browser [2] die gesamte [Nuxt]-Anwendung, die dann im SPA-Modus ausgeführt wird. Der [UI]-Block (User Interface) [4] zeigt dem Benutzer [Vue.js]-Seiten an. Benutzeraktionen oder der Lebenszyklus der Seite können Anfragen nach externen Daten vom Datenserver [3] auslösen. Die [DAO]-Schicht [5] führt dann die erforderlichen HTTP-Anfragen durch;
Wir verwenden Version 14 des Steuerberechnungsservers, der im Dokument |Einführung in PHP7 anhand von Beispielen| entwickelt wurde. Wir nutzen nur einen Teil seiner JSON-API (Application Programming Interface):
Anfrage | Antwort |
| |
| |
| |
| |
15.5.1. Die [DAO]-Schicht des [Nuxt]-Servers

Der [node.js]-Server [1] verwendet die [DAO]-Schicht, die im Dokument |Einführung in das VUE.JS-Framework anhand von Beispielen| beschrieben wird. Hier noch einmal der Code:
'use strict';
// imports
import qs from 'qs'
class Dao {
// manufacturer
constructor(axios) {
this.axios = axios;
// session cookie
this.sessionCookieName = "PHPSESSID";
this.sessionCookie = '';
}
// init session
async initSession() {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// URL parameters
params: {
action: 'init-session',
type: 'json'
}
};
// execute query HTTP
return await this.getRemoteData(options);
}
async authentifierUtilisateur(user, password) {
// query options HHTP [post /main.php?action=authenticate-user]
const options = {
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// body of POST
data: qs.stringify({
user: user,
password: password
}),
// URL parameters
params: {
action: 'authentifier-utilisateur'
}
};
// execute query HTTP
return await this.getRemoteData(options);
}
async getAdminData() {
// query options HHTP [get /main.php?action=get-admindata]
const options = {
method: "GET",
// URL parameters
params: {
action: 'get-admindata'
}
};
// execute query HTTP
const data = await this.getRemoteData(options);
// result
return data;
}
async getRemoteData(options) {
// for the session cookie
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = this.sessionCookie;
// execute query HTTP
let response;
try {
// asynchronous request
response = await this.axios.request('main.php', options);
} catch (error) {
// the [error] parameter is an exception instance - it can take various forms
if (error.response) {
// the server response is in [error.response]
response = error.response;
} else {
// error restart
throw error;
}
}
// response is the entire HTTP response from the server (HTTP headers + response itself)
// retrieve the session cookie if it exists
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie is an array
// look for the session cookie in this table
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// look for the session cookie
const results = RegExp('^(' + this.sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// the session cookie is stored
// eslint-disable-next-line require-atomic-updates
this.sessionCookie = results[1];
// we found
trouvé = true;
} else {
// next item
i++;
}
}
}
// the server response is in [response.data]
return response.data;
}
}
// class export
export default Dao;
- Alle Methoden in der [dao]-Schicht geben das vom Datenserver gesendete Objekt [{action: ‘xx’, status: nn, response: {...}] zurück mit:
- [action]: den Namen der vom Datenserver ausgeführten Aktion;
- [state]: numerischer Indikator:
- [initSession]: status=700 für eine fehlerfreie Antwort;
- [authenticateUser]: status=200 für eine Antwort ohne Fehler;
- [getAdminData]: status=1000 für eine Antwort ohne Fehler;
- [end-session]: status=400 für eine Antwort ohne Fehler;
- [response]: Antwort, die mit dem numerischen Indikator [status] verknüpft ist. Kann je nach diesem numerischen Indikator variieren;
Betrachten wir den Konstruktor der Klasse [Dao]:
// constructeur
constructor(axios) {
this.axios = axios;
// cookie de session
this.sessionCookieName = "PHPSESSID";
this.sessionCookie = '';
}
- Zeile 2: Das als Argument an den Konstruktor übergebene [axios]-Objekt wird vom aufrufenden Code bereitgestellt. Dieses Objekt führt die HTTP-Anfragen durch;
- Zeile 5: Der Name des vom Datenserver gesendeten Sitzungscookies, geschrieben in PHP;
- Zeile 6: das zwischen der [dao]-Schicht und dem Datenserver ausgetauschte Sitzungscookie. Dieses wird durch die Funktion [getRemoteData] in den Zeilen 67–113 initialisiert;
Für das Session-Cookie müssen wir zwei separate [dao]-Schichten betrachten:
- die Browser-Schicht;
- die Server-Schicht;
Wir müssen drei Session-Cookies verwalten:
- dasjenige, das zwischen dem [nuxt]-Client und dem PHP 7-Server ausgetauscht wird;
- das zwischen dem [nuxt]-Server und dem PHP 7-Server ausgetauschte;
- das zwischen dem [nuxt]-Client und dem [nuxt]-Server ausgetauschte;
Wir stellen sicher, dass das Sitzungscookie mit dem PHP-Server sowohl für den Client als auch für den [nuxt]-Server identisch ist. Wir bezeichnen dieses Cookie als PHP-Sitzungscookie. Dieses Cookie ist dasjenige aus den Fällen 1 und 2. Das Cookie aus Fall 3 bezeichnen wir als [nuxt]-Sitzungscookie. Wir haben somit zwei Sitzungen:
- eine PHP-Sitzung mit dem PHP-Sitzungscookie;
- eine [nuxt]-Sitzung mit dem [nuxt]-Sitzungscookie;
Warum verwenden wir dasselbe Cookie für die PHP-Sitzungen des Clients und die [nuxt]-Sitzungen des Browsers? Wir möchten, dass die Anwendung mit dem PHP-7-Server kommunizieren kann, unabhängig davon, ob es sich um den Client oder den [nuxt]-Server handelt:
- Wenn eine Aktion A vom [nuxt]-Server den PHP-Server in den Zustand E versetzt, spiegelt sich dieser Zustand in der vom PHP-Server verwalteten PHP-Sitzung wider;
- Durch die Verwendung desselben PHP-Sitzungscookies wie der Server würde eine Client-Aktion B [nuxt], die auf die Server-Aktion A [nuxt] folgt, den PHP-Server in dem vom [nuxt]-Server hinterlassenen Zustand E vorfinden und könnte somit auf der bereits vom [nuxt]-Server geleisteten Arbeit aufbauen;
- Wenn nach der Aktion B vom [nuxt]-Client eine Aktion C vom [nuxt]-Server folgt, kann diese Aktion aus demselben Grund wie zuvor auf der von der Aktion B vom [nuxt]-Client geleisteten Arbeit aufbauen;
Damit der Browser des [nuxt]-Clients mit dem PHP-Server für die Steuerberechnung kommunizieren kann, verwenden wir Version 14 dieses Servers, die domänenübergreifende Aufrufe zulässt – d. h. Aufrufe von einem Browser an den PHP-Server. Aufrufe vom [nuxt]-Server an den PHP-Server sind jedoch keine domänenübergreifenden Aufrufe. Dieses Konzept gilt nur für Aufrufe, die von einem Browser aus erfolgen.
Kehren wir zum Konstruktor-Code der vorherigen [Dao]-Klasse zurück:
// constructeur
constructor(axios) {
this.axios = axios;
// cookie de session
this.sessionCookieName = "PHPSESSID";
this.sessionCookie = '';
}
- Die Zeilen 5 und 6 beziehen sich auf das PHP-Sitzungscookie mit dem Steuerberechnungsserver;
Die Verwaltung des oben genannten PHP-Sitzungs-Cookies ist für den [nuxt]-Server nicht geeignet: Seine [dao]-Schicht wird bei jeder neuen Anfrage an den [nuxt]-Server instanziiert. Denken Sie daran, dass das Anfordern einer Seite vom [nuxt]-Server die [nuxt]-Anwendung effektiv zurücksetzt. Wenn der [nuxt]-Server also seine erste Anfrage an den Datenserver stellt, wird das PHP-Sitzungs-Cookie für die [dao]-Schicht initialisiert; dieser Wert geht jedoch bei der nächsten HTTP-Anfrage desselben [nuxt]-Servers verloren, da in der Zwischenzeit dessen [dao]-Schicht neu erstellt, der Konstruktor erneut ausgeführt und das PHP-Sitzungs-Cookie auf eine leere Zeichenkette zurückgesetzt wurde (Zeile 6);
Eine Lösung besteht darin, einen anderen Konstruktor für die [DAO]-Schicht des Servers zu verwenden:
// constructeur
constructor(axios, phpSessionCookie) {
// bibliothèque axios
this.axios = axios
// valeur du cookie de session
this.phpSessionCookie = phpSessionCookie
// nom du cookie de session du serveur PHP
this.phpSessionCookieName = 'PHPSESSID'
}
- Zeile 2: Diesmal wird das PHP-Sitzungs-Cookie an den Konstruktor der [DAO]-Schicht des Datenservers übergeben;
Wie stellt der [nuxt]-Server dieses PHP-Sitzungs-Cookie dem Konstruktor seiner [dao]-Schicht zur Verfügung? Wir speichern das PHP-Sitzungs-Cookie in dem [nuxt]-Sitzungs-Cookie, das zwischen dem Browser und dem [nuxt]-Server ausgetauscht wird. Der Vorgang läuft wie folgt ab:
- Die [nuxt]-Anwendung wird gestartet;
- Wenn der [nuxt]-Server seine erste HTTP-Anfrage an den PHP-Server stellt, speichert er das empfangene PHP-Sitzungscookie in dem [nuxt]-Sitzungscookie, das er mit dem [nuxt]-Client austauscht;
- Der Browser, auf dem der [nuxt]-Client läuft, empfängt dieses [nuxt]-Sitzungs-Cookie und sendet es daher automatisch mit jeder neuen Anfrage an den [nuxt]-Server zurück;
- wenn der [nuxt]-Server eine neue Anfrage an den PHP-Server stellen muss, findet er das PHP-Sitzungs-Cookie in dem [nuxt]-Sitzungs-Cookie, das der Browser ihm gesendet hat. Er sendet es dann an den PHP-Server;
Es gibt tatsächlich zwei Session-Cookies, und diese dürfen nicht verwechselt werden:
- das [nuxt]-Sitzungscookie, das zwischen dem [nuxt]-Server und dem Browser des [nuxt]-Clients ausgetauscht wird;
- das PHP-Sitzungs-Cookie, das zwischen dem [nuxt]-Server und dem PHP-Server oder zwischen dem [nuxt]-Client und dem PHP-Server ausgetauscht wird;
Kehren wir nun zum Code für die [Dao]-Klassenmethode zurück. Er enthält keine Funktion zum Schließen der PHP-Sitzung mit dem Steuerberechnungsserver. Diese fügen wir hinzu:
// end of tax calculation session
async finSession() {
// query options HHTP [get /main.php?action=end-session]
const options = {
method: 'GET',
// URL parameters
params: {
action: 'fin-session'
}
}
// execute query HTTP
const data = await this.getRemoteData(options)
// result
return data
}
Beim Testen stellen wir fest, dass die in Zeile 12 aufgerufene Funktion [getRemoteData] für die Methode [finSession] nicht geeignet ist:
async getRemoteData(options) {
// for the session cookie
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = this.sessionCookie;
// execute query HTTP
let response;
try {
// asynchronous request
response = await this.axios.request('main.php', options);
} catch (error) {
// the [error] parameter is an exception instance - it can take various forms
if (error.response) {
// the server response is in [error.response]
response = error.response;
} else {
// error restart
throw error;
}
}
// response is the entire HTTP response from the server (HTTP headers + response itself)
// retrieve the session cookie if it exists
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie is an array
// look for the session cookie in this table
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// look for the session cookie
const results = RegExp('^(' + this.sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// the session cookie is stored
// eslint-disable-next-line require-atomic-updates
this.sessionCookie = results[1];
// we found
trouvé = true;
} else {
// next item
i++;
}
}
}
// the server response is in [response.data]
return response.data;
}
- Zeilen 30–43: Wir suchen nach dem Cookie [PHPSESSID=xxx]. Wird es gefunden, wird es in der Klasse gespeichert (Zeile 36);
Dieser Code ist für die neue [finSession]-Methode nicht geeignet, da der PHP-Server bei der [fin-session]-Aktion zwei Cookies mit dem Namen [PHPSESSID] sendet. Hier ist ein Beispiel, das mit einem [Postman]-Client erstellt wurde:

- in [1] die Anfrage vom [Postman]-Client;
- in [3] die Antwort des PHP-Servers;
- in [4] die HTTP-Header der Antwort des PHP-Servers;

- In [5] teilt der PHP-Server zunächst mit, dass er die aktuelle PHP-Sitzung gelöscht hat;
- in [6] sendet der PHP-Server das Cookie für die neue PHP-Sitzung;
Mit dem aktuellen Code ruft die Funktion [getRemoteData] das Cookie [5] ab, während eigentlich das Cookie [6] gespeichert werden muss.
Wir müssen daher den Code für die Funktion [getRemoteData] aktualisieren:
async getRemoteData(options) {
// is there a PHP session cookie?
if (this.phpSessionCookie) {
// are there headers?
if (!options.headers) {
// create an empty object
options.headers = {}
}
// session cookie header PHP
options.headers.Cookie = this.phpSessionCookie
}
// execute query HTTP
let response
try {
// asynchronous request
response = await this.axios.request('main.php', options)
} catch (error) {
// the [error] parameter is an exception instance - it can take various forms
if (error.response) {
// the server response is in [error.response]
response = error.response
} else {
// error restart
throw error
}
}
// response is the entire HTTP response from the server (HTTP headers + response itself)
// look for session cookie PHP in received cookies
// all cookies received
const cookies = response.headers['set-cookie']
if (cookies) {
// cookies is a picture
// look for the PHP session cookie in this array
let trouvé = false
let i = 0
while (!trouvé && i < cookies.length) {
// look for the PHP session cookie
const results = RegExp('^(' + this.phpSessionCookieName + '.+?)$').exec(cookies[i])
if (results) {
// we store the PHP session cookie
const phpSessionCookie = results[1]
// is the word [deleted] in it?
const results2 = RegExp(this.phpSessionCookieName + '=deleted').exec(phpSessionCookie)
if (!results2) {
// we have the right session cookie PHP
this.phpSessionCookie = phpSessionCookie
// we found
trouvé = true
} else {
// next item
i++
}
} else {
// next item
i++
}
}
}
// the server response is in [response.data]
return response.data
}
- Zeile 41: Wir haben ein Cookie mit dem Namen [PHPSESSID] gefunden. Wir speichern es lokal;
- Zeile 43: Wir prüfen, ob das gespeicherte Cookie die Zeichenfolge [PHPSESSID=deleted] enthält;
- Zeile 46: Wenn die Antwort „nein“ lautet, haben wir das richtige Cookie [PHPSESSID] gefunden. Wir speichern es in der Klasse;
Nach der Funktion [getRemoteData] wird das PHP-Session-Cookie in der Klasse unter [this.phpSessionCookie] gespeichert. Wir haben erwähnt, dass die Klasse bei jeder neuen HTTP-Anfrage vom [nuxt]-Server instanziiert wird. Das PHP-Session-Cookie muss daher aus der Klasse extrahiert werden. Dazu fügen wir ihr eine neue Methode hinzu:
// accès au cookie de la session PHP
getPhpSessionCookie() {
return this.phpSessionCookie
}
- Der [nuxt]-Server fordert eine Aktion von seiner [dao]-Schicht an, indem er dem Konstruktor das PHP-Session-Cookie übergibt, sofern vorhanden;
- Sobald die Aktion abgeschlossen ist, ruft der [nuxt]-Server das von der [dao]-Schicht gespeicherte PHP-Session-Cookie mithilfe der zuvor genannten [getPhpSessionCookie]-Methode ab. Dieses Cookie kann mit dem vorherigen identisch sein oder ein anderes sein. Letzteres tritt in zwei Fällen auf:
- wenn die Methode [initSession] ausgeführt wird (vorher gab es kein PHP-Session-Cookie);
- wenn die Methode [finSession] ausgeführt wird (der PHP-Server ändert das PHP-Sitzungs-Cookie);
Beachten Sie eine Besonderheit bezüglich des PHP-Sitzungs-Cookies. Der [nuxt]-Server erhält dieses Cookie nicht immer vom PHP-Server. Tatsächlich sendet der PHP-Server es nur einmal. Danach sendet er es nicht mehr. Wenn wir uns den Code für [getRemoteData] und [getPhpSessionCookie] ansehen, können wir feststellen, dass die Funktion [getPhpSessionCookie] das dem Konstruktor übergebene PHP-Sitzungs-Cookie zurückgibt, wenn der PHP-Server kein Sitzungs-Cookie sendet. Auf diese Weise sendet der Server dem PHP-Server immer das letzte PHP-Sitzungs-Cookie, das der PHP-Server an ihn gesendet hat.
15.5.2. Die [dao]-Schicht des [nuxt]-Clients

Für den [nuxt]-Client, der in einem Browser läuft, verwenden wir den Code aus der [Dao]-Klasse im Dokument |Einführung in das VUE.JS-Framework anhand von Beispielen|:
"use strict";
// imports
import qs from "qs";
class Dao {
// manufacturer
constructor(axios) {
this.axios = axios;
}
// init session
async initSession() {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// URL parameters
params: {
action: "init-session",
type: "json"
}
};
// execute query HTTP
return await this.getRemoteData(options);
}
async authentifierUtilisateur(user, password) {
// query options HHTP [post /main.php?action=authenticate-user]
const options = {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded"
},
// body of POST
data: qs.stringify({
user: user,
password: password
}),
// URL parameters
params: {
action: "authentifier-utilisateur"
}
};
// execute query HTTP
return await this.getRemoteData(options);
}
async getAdminData() {
// query options HHTP [get /main.php?action=get-admindata]
const options = {
method: "GET",
// URL parameters
params: {
action: "get-admindata"
}
};
// execute query HTTP
const data = await this.getRemoteData(options);
// result
return data;
}
async getRemoteData(options) {
// execute query HTTP
let response;
try {
// asynchronous request
response = await this.axios.request("main.php", options);
} catch (error) {
// the [error] parameter is an exception instance - it can take various forms
if (error.response) {
// the server response is in [error.response]
response = error.response;
} else {
// error restart
throw error;
}
}
// response is the entire HTTP response from the server (HTTP headers + response itself)
// the server response is in [response.data]
return response.data;
}
}
// class export
export default Dao;
Dieser Code unterscheidet sich von der [dao]-Schicht des [nuxt]-Servers darin, dass er das PHP-Session-Cookie nicht mit dem Server für die Steuerberechnung verwaltet: Das übernimmt der Browser.
Wir werden, wie bereits bei der [dao]-Schicht des [nuxt]-Servers, eine [finSession]-Methode hinzufügen:
// end of tax calculation session
async finSession() {
// query options HHTP [get /main.php?action=end-session]
const options = {
method: 'GET',
// URL parameters
params: {
action: 'fin-session'
}
}
// execute query HTTP
const data = await this.getRemoteData(options)
// result
return data
}
Wenn der [nuxt]-Client diese Methode ausführt, erhält er, genau wie der [nuxt]-Server, zwei PHP-Sitzungscookies. Tatsächlich ist es der Browser, der diese empfängt, und er geht korrekt damit um: Er behält nur das Cookie für die neue PHP-Sitzung, die vom Steuerberechnungsserver initiiert wurde. Wenn der [nuxt]-Client also das nächste Mal eine Anfrage an den PHP-Server sendet, ist das PHP-Sitzungscookie korrekt, da es vom Browser gesendet wird. Es gibt jedoch ein Problem: Der [nuxt]-Server weiß nicht, dass sich das PHP-Sitzungs-Cookie geändert hat. Bei seiner Kommunikation mit dem PHP-Server sendet er daher ein PHP-Sitzungs-Cookie, das nicht mehr existiert, was zu Problemen führt. Der [nuxt]-Client muss den [nuxt]-Server darüber informieren, dass sich das PHP-Sitzungs-Cookie geändert hat, und es an den Server weiterleiten. Wir wissen, wie dies geschehen kann: über das [nuxt]-Sitzungs-Cookie, das zwischen dem Client und dem [nuxt]-Server ausgetauscht wird. Der [nuxt]-Client hat mindestens zwei Möglichkeiten, das neue PHP-Sitzungs-Cookie abzurufen:
- indem er es vom Browser anfordert;
- durch Verwendung der [getRemoteData]-Methode des Servers, der weiß, wie das neue PHP-Sitzungs-Cookie abgerufen wird;
Wir werden die zweite Lösung verwenden, da sie bereits einsatzbereit ist. Die [getRemoteData]-Methode des [nuxt]-Clients sieht dann wie folgt aus:
async getRemoteData(options) {
// execute query HTTP
let response
try {
// asynchronous request
response = await this.axios.request('main.php', options)
} catch (error) {
// the [error] parameter is an exception instance - it can take various forms
if (error.response) {
// the server response is in [error.response]
response = error.response
} else {
// error restart
throw error
}
}
// response is the entire HTTP response from the server (HTTP headers + response itself)
// look for session cookie PHP in received cookies
// all cookies received
const cookies = response.headers['set-cookie']
if (cookies) {
// cookies is a picture
// look for session cookie PHP in this array
let trouvé = false
let i = 0
while (!trouvé && i < cookies.length) {
// look for the PHP session cookie
const results = RegExp('^(' + this.phpSessionCookieName + '.+?)$').exec(cookies[i])
if (results) {
// we store the PHP session cookie
const phpSessionCookie = results[1]
// is the word [deleted] in it?
const results2 = RegExp(this.phpSessionCookieName + '=deleted').exec(phpSessionCookie)
if (!results2) {
// we have the right session cookie PHP
this.phpSessionCookie = phpSessionCookie
// we found
trouvé = true
} else {
// next item
i++
}
} else {
// next item
i++
}
}
}
// the server response is in [response.data]
return response.data
}
Wir haben nur den Code in [getRemoteData] beibehalten, der die Antwort des PHP-Servers verarbeitet, um das PHP-Sitzungs-Cookie abzurufen. Den Code, der das PHP-Sitzungs-Cookie in die Anfrage an den PHP-Server einfügt, haben wir nicht beibehalten, da dies vom Browser übernommen wird, auf dem der [nuxt]-Client läuft.
Sobald das PHP-Sitzungs-Cookie vom [nuxt]-Client abgerufen wurde, muss es in die [nuxt]-Sitzung eingefügt werden, damit der [nuxt]-Server es verwenden kann. Die [dao]-Schicht übernimmt dies nicht, stellt aber über eine Methode Zugriff auf das von ihr gespeicherte PHP-Sitzungs-Cookie bereit:
// accès au cookie de la session PHP
getPhpSessionCookie() {
return this.phpSessionCookie
}
Die Funktion [getPhpSessionCookie] gibt nicht immer ein gültiges Session-Cookie zurück:
- Hierbei ist zu beachten, dass die [dao]-Schicht des [nuxt]-Clients persistent ist. Sie wird einmal instanziiert und verbleibt dann im Speicher;
- solange der PHP-Server kein PHP-Session-Cookie an den [nuxt]-Client sendet, gibt die Funktion [getPhpSessionCookie] des [nuxt]-Clients den Wert [undefined] zurück;
- wenn der PHP-Server ein PHP-Session-Cookie an den [nuxt]-Client sendet, wird dieses in [this.phpSessionCookie] gespeichert und verbleibt dort, bis es durch ein neues, vom PHP-Server gesendetes PHP-Session-Cookie ersetzt wird. Die Funktion [getPhpSessionCookie] des [nuxt]-Clients gibt dann das zuletzt empfangene PHP-Session-Cookie zurück;
Die [dao]-Schicht des [nuxt]-Clients unterscheidet sich von der des [nuxt]-Servers nur in einem Punkt: Sie sendet das PHP-Session-Cookie nicht selbst, da dies vom Browser übernommen wird. Dennoch haben wir uns dafür entschieden, zwei getrennte [dao]-Schichten beizubehalten, da die Gründe für ihre jeweiligen Implementierungen unterschiedlich sind.
15.6. Die [nuxt]-Sitzung
![]()
Die [nuxt]-Sitzung (zwischen dem Client und dem Nuxt-Server) wird in dem folgenden [session]-Objekt gekapselt:
/* eslint-disable no-console */
// définition de la session
const session = {
// contenu de la session
value: {
// store non initialisé
initStoreDone: false,
// valeur du store Vuex
store: ''
},
// sauvegarde de la session dans un cookie
save(context) {
// sauvegarde du store en session
this.value.store = context.store.state
console.log('nuxt-session save=', this.value)
// sauvegarde de la valeur de la session
context.app.$cookies.set('nuxt-session', this.value, { path: context.base, maxAge: context.env.maxAge })
},
// reset de la session
reset(context) {
console.log('nuxt-session reset')
// reset du store
context.store.commit('reset')
// sauvegarde du nouveau store en session et sauvegarde de la session
this.save(context)
}
}
// export de la session
export default session
- Zeilen 5–10: Die Session hat nur eine Eigenschaft [value] mit zwei Untereigenschaften:
- [initStoreDone], die angibt, ob der Store initialisiert wurde oder nicht;
- [store]: der Wert [store.state] des Vuex-Stores der Anwendung;
- Zeilen 12–18: Die Methode [save] wird verwendet, um die [nuxt]-Sitzung in einem Cookie zu speichern. Hier verwenden wir die Bibliothek [cookie-universal-nuxt], um das Cookie zu verwalten. Beachten Sie den Namen des [nuxt]-Sitzungscookies: [nuxt-session] (Zeile 17);
- Zeilen 20–26: Die Methode [reset] setzt die [nuxt]-Sitzung zurück;
- Zeile 23: Der Vuex-Store wird zurückgesetzt und dann in Zeile 25 in der Sitzung gespeichert;
15.7. [nuxt]-Plugins zur Sitzungsverwaltung

15.7.1. Das [nuxt]-Plugin zur Sitzungsverwaltung für den [nuxt]-Server
Wenn die Anwendung startet, wird zuerst der [nuxt]-Server ausgeführt. Er ist daher für die Initialisierung der [nuxt]-Sitzung zuständig. Das Skript [server/plgSession] lautet wie folgt:
/* eslint-disable no-console */
// import de la session
import session from '@/entities/session'
export default (context, inject) => {
// gestion de la session serveur
console.log('[plugin server plgSession]')
// y-a-t-il une session existante ?
const value = context.app.$cookies.get('nuxt-session')
if (!value) {
// nouvelle session
console.log("[plugin server plgSession], démarrage d'une nouvelle session")
} else {
// session existante
console.log("[plugin server plgSession], reprise d'une session existante")
session.value = value
}
// on injecte une fonction dans [context, Vue] qui rendra la session courante
inject('session', () => session)
}
- Zeile 4: Importiere den [nuxt]-Session-Code;
- Zeile 11: Abrufen des Werts des [nuxt]-Session-Cookies;
- Zeilen 12–15: Wenn das [nuxt]-Sitzungscookie nicht existierte, reicht die in Zeile 4 importierte [nuxt]-Sitzung aus. Es ist nichts weiter zu tun;
- Zeilen 15–19: Wenn das [nuxt]-Sitzungscookie existierte, speichern wir in Zeile 18 dessen Wert in der in Zeile 4 importierten Sitzung;
- Zeile 22: Die Sitzung wurde entweder initialisiert oder wiederhergestellt. Wir stellen sie über die Funktion [$session] zur Verfügung;
15.7.2. Das [nuxt]-Sitzungsverwaltungs-Plugin für den [nuxt]-Client
Das Skript [client/plgSession] lautet wie folgt:
/* eslint-disable no-console */
// import de la session
import session from '@/entities/session'
export default (context, inject) => {
// gestion de la session client
console.log('[plugin client plgSession], reprise de la session [nuxt] du serveur')
// on récupère la session existante du serveur nuxt
session.value = context.app.$cookies.get('nuxt-session')
// on injecte une fonction dans [context, Vue] qui rendra la session courante
inject('session', () => session)
}
- Zeile 4: Die [nuxt]-Sitzung wird importiert;
- Zeile 10: Wir rufen die aktuelle [nuxt]-Sitzung aus dem [nuxt-session]-Cookie ab;
- Zeile 13: Wir geben die in Zeile 4 importierte [nuxt]-Sitzung über die injizierte Funktion [$session] zurück;
15.8. Plugins für die [dao]-Ebenen

15.8.1. Das [dao]-Layer-Plugin für den [nuxt]-Client
Das Skript [client/plgDao] lautet wie folgt:
/* eslint-disable no-console */
// on crée un point d'accès à la couche [Dao]
import Dao from '@/api/client/Dao'
export default (context, inject) => {
// configuration axios
context.$axios.defaults.timeout = context.env.timeout
context.$axios.defaults.baseURL = context.env.baseURL
context.$axios.defaults.withCredentials = context.env.withCredentials
// instanciation de la couche [dao]
const dao = new Dao(context.$axios)
// injection d'une fonction [$dao] dans le contexte
inject('dao', () => dao)
// log
console.log('[fonction client $dao créée]')
}
- Zeile 3: Die [dao]-Schicht des [nuxt]-Clients wird importiert;
- Zeilen 6–8: Wir konfigurieren das Objekt [context.$axios], das HTTP-Anfragen für die [dao]-Schicht des [nuxt]-Clients unter Verwendung von Informationen aus der Datei [nuxt.config] stellt:
// environnement
env: {
// configuration axios
timeout: 2000,
withCredentials: true,
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
// configuration du cookie de session [nuxt]
maxAge: 60 * 5
}
- Zeile 10: Die [dao]-Schicht des [nuxt]-Clients wird instanziiert;
- Zeile 12: Die Funktion [$dao] wird in den Kontext und die Seiten des Clients eingefügt. Diese Funktion ermöglicht den Zugriff auf die [dao]-Schicht aus Zeile 10;
Um also auf die [dao]-Schicht des [nuxt]-Clients zuzugreifen, während dieser läuft, schreiben wir:
- [context.app.$dao()], wobei der Kontext bekannt ist;
- [this.$dao()] in einer [Vue.js]-Seite;
15.8.2. Das [dao]-Layer-Plugin für den [nuxt]-Server
Das Skript [server/plgDao] lautet wie folgt:
/* eslint-disable no-console */
// on crée un point d'accès à la couche [Dao]
import Dao from '@/api/server/Dao'
export default (context, inject) => {
// configuration axios
context.$axios.defaults.timeout = context.env.timeout
context.$axios.defaults.baseURL = context.env.baseURL
// on récupère le cookie de session
const store = context.app.$session().value.store
const phpSessionCookie = store ? store.phpSessionCookie : ''
console.log('session=', context.app.$session().value, 'phpSessionCookie=', phpSessionCookie)
// instanciation de la couche [dao]
const dao = new Dao(context.$axios, phpSessionCookie)
// injection d'une fonction [$dao] dans le contexte
inject('dao', () => dao)
// log
console.log('[fonction server $dao créée]')
}
- Zeile 3: Die [dao]-Schicht des [nuxt]-Servers wird importiert;
- Zeilen 6–7: Das Objekt [context.$axios] wird so konfiguriert, dass es HTTP-Anfragen für die [dao]-Schicht des [nuxt]-Servers unter Verwendung von Informationen aus der Datei [nuxt.config] stellt:
// environnement
env: {
// configuration axios
timeout: 2000,
withCredentials: true,
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
// configuration du cookie de session [nuxt]
maxAge: 60 * 5
}
- Zeile 9: Abrufen des Anwendungsspeichers [nuxt];
- Zeile 10: Wenn der Store vorhanden ist, rufen wir das PHP-Session-Cookie ab, da wir es benötigen, um die [dao]-Schicht des [nuxt]-Servers zu instanziieren;
- Zeile 13: Instanziieren der [dao]-Schicht des [nuxt]-Servers;
- Zeile 15: Die Funktion [$dao] wird in den Kontext und die Seiten des [nuxt]-Servers injiziert. Diese Funktion ermöglicht den Zugriff auf die [dao]-Schicht aus Zeile 13;
Um also auf die [dao]-Schicht des [nuxt]-Servers zuzugreifen, wenn dieser läuft, schreiben wir:
- [context.app.$dao()], wobei der Kontext bekannt ist;
- [this.$dao()] auf einer [Vue.js]-Seite;
15.9. Der Vuex-Store
![]()
Der [Vuex]-Store speichert alle Daten, die von den verschiedenen Komponenten der Anwendung [Seiten, Client, Server] gemeinsam genutzt werden müssen, ohne dass diese Daten reaktiv sind.
/* eslint-disable no-console */
// awning status
export const state = () => ({
// session jSON started
jsonSessionStarted: false,
// authenticated user
userAuthenticated: false,
// session cookie PHP
phpSessionCookie: '',
// adminData
adminData: ''
})
// changes in the awning
export const mutations = {
// state replacement
replace(state, newState) {
for (const attr in newState) {
state[attr] = newState[attr]
}
},
// awning reset
reset() {
this.commit('replace', { jsonSessionStarted: false, userAuthenticated: false, phpSessionCookie: '', adminData: '' })
}
}
// awning actions
export const actions = {
nuxtServerInit(store, context) {
// who executes this code?
console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server, 'env=', context.env)
// init session
initStore(store, context)
}
}
function initStore(store, context) {
// store is the blind to be initialized
// retrieve the session
const session = context.app.$session()
// has the session already been initiated?
if (!session.value.initStoreDone) {
// start a new blind
console.log("nuxtServerInit, initialisation d'une nouvelle session")
// put the blind in the session
session.value.store = store.state
// the blind is now initialized
session.value.initStoreDone = true
} else {
console.log("nuxtServerInit, reprise d'un store existant")
// update the store with the session store
store.commit('replace', session.value.store)
}
// save the session
session.save(context)
// log
console.log('initStore terminé, store=', store.state)
}
Die im Store gespeicherten Daten lauten wie folgt:
- Zeile 6: [jsonSessionStarted] wird auf „true“ gesetzt, sobald eine JSON-Sitzung mit dem PHP-Server erfolgreich initialisiert wurde, unabhängig davon, ob diese vom Client oder vom [nuxt]-Server initiiert wurde. Nach Abschluss dieser Initialisierung wird das Sitzungs-Cookie für den PHP-Server abgerufen und in der Eigenschaft [phpSessionCookie] gespeichert (Zeile 10);
- Zeile 8: [userAuthenticated] wird auf „true“ gesetzt, sobald die Authentifizierung beim PHP-Server erfolgreich ist, unabhängig davon, ob sie vom Client oder vom [nuxt]-Server durchgeführt wurde;
- Zeile 12: [adminData] ist der Wert [adminData], der nach erfolgreicher Authentifizierung vom PHP-Server abgerufen wird;
- Zeilen 18–22: Die Operation [replace] initialisiert die vorherigen Eigenschaften mit denen eines als Parameter übergebenen Objekts;
- Zeilen 24–26: Die Mutation [reset] setzt die Store-Eigenschaften auf ihre Ausgangswerte zurück;
- Zeilen 31–37: Die Funktion [nuxtServerInit] delegiert ihre Arbeit an die Funktion [initStore];
- Zeilen 39–60: Die Funktion [initStore] hat zwei Aufgaben:
- Wenn der Store noch nicht initialisiert wurde, wird er initialisiert und der Sitzung hinzugefügt;
- Wenn der Store bereits initialisiert wurde, wird sein Wert aus der [nuxt]-Session abgerufen;
- Zeile 42: Die nuxt-Session wird abgerufen;
- Zeile 44: Wir prüfen, ob der Store initialisiert wurde:
- Wenn nicht, wird der anfängliche Store in die Sitzung eingefügt (Zeile 48);
- dann geben wir in Zeile 50 an, dass der Store initialisiert wurde;
- Zeilen 51–55: Wenn der Store initialisiert wurde, verwenden wir ihn in Zeile 54, um den Store mit dem in der Session enthaltenen Wert zu initialisieren;
- Zeile 57: In allen Fällen wird die Sitzung zusammen mit dem darin enthaltenen Store im [nuxt-session]-Cookie gespeichert;
15.10. Das [plgEventBus]-Plugin

Dieses Plugin zielt darauf ab, dem [nuxt]-Client über eine in den [nuxt]-Client-Kontext injizierte [$eventBus]-Funktion einen Event-Bus zugänglich zu machen. Es ist nicht notwendig, es in den [nuxt]-Server-Kontext zu injizieren, da der Server keine Ereignisse verarbeiten kann. Wir haben jedoch bereits gesehen, dass das Injizieren auf der Serverseite und die anschließende Verwendung keinen Fehler verursacht.
/* eslint-disable no-console */
// 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)
// log
console.log('[fonction $eventBus créée]')
}
Wir sind diesem Plugin bereits im Abschnitt „Links“ begegnet. Die Funktion [$eventBus] steht dem Client über die folgende Notation zur Verfügung:
- [context.app.$eventBus()], sofern der Kontext verfügbar ist;
- [this.$eventBus()] in den [Vue.js]-Seiten des Clients;
15.11. Die Komponenten der [Nuxt]-Anwendung

Die [layout]-Komponente ist die aus den vorherigen Beispielen:
<!-- view layout -->
<template>
<!-- line -->
<div>
<b-row>
<!-- three-column zone -->
<b-col v-if="left" cols="3">
<slot name="left" />
</b-col>
<!-- nine-column zone -->
<b-col v-if="right" cols="9">
<slot name="right" />
</b-col>
</b-row>
</div>
</template>
<script>
export default {
// paramètres
props: {
left: {
type: Boolean
},
right: {
type: Boolean
}
}
}
</script>
Die [Navigations-]Komponente sieht wie folgt aus:
<template>
<!-- bootstrap menu with three options -->
<b-nav vertical>
<b-nav-item to="/authentification" exact exact-active-class="active">
Authentification
</b-nav-item>
<b-nav-item to="/get-admindata" exact exact-active-class="active">
Requête AdminData
</b-nav-item>
<b-nav-item to="/fin-session" exact exact-active-class="active">
Fin session impôt
</b-nav-item>
</b-nav>
</template>
15.12. Die [nuxt]-Anwendungslayouts

15.12.1. [default]
Das [default]-Layout ist dasjenige, das für das [nuxt-11]-Beispiel im verlinkten Absatz verwendet wird:
<template>
<div class="container">
<b-card>
<!-- un message -->
<b-alert show variant="success" align="center">
<h4>[nuxt-12] : requêtes HTTP avec axios</h4>
</b-alert>
<!-- la vue courante du routage -->
<nuxt />
<!-- message d’attente -->
<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 d’une opération asynchrone -->
<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]')
if (process.client) {
// listen to the evt [loading]
this.$eventBus().$on('loading', this.mShowLoading)
// and event [errorLoadingMessage]
this.$eventBus().$on('errorLoading', this.mShowErrorLoading)
}
},
beforeMount() {
console.log('[default beforeMount]')
},
mounted() {
console.log('[default mounted]')
},
methods: {
// message waiting management
mShowLoading(value) {
console.log('[default mShowLoading], showLoading=', value)
this.showLoading = value
},
// asynchronous operation error
mShowErrorLoading(value, errorLoadingMessage) {
console.log('[default mShowErrorLoading], showErrorLoading=', value, 'errorLoadingMessage=', errorLoadingMessage)
this.showErrorLoading = value
this.errorLoadingMessage = errorLoadingMessage
}
}
}
</script>
- Zeilen 10–14: Anzeige der Meldung, dass der Client [nuxt] auf den Abschluss einer asynchronen Operation wartet;
- Zeilen 15–18: Zeigt etwaige Fehlermeldungen aus einer asynchronen Operation an;
- Zeile 37: Die Funktion [created] der Seite [default] wird vor der Funktion [mounted] der Seiten ausgeführt;
- Zeile 39: Wenn der Ausführende der [nuxt]-Client ist, wartet die [default]-Seite auf
- [loading], was den Beginn oder das Ende einer Wartezeit signalisiert. Die Funktion [mShowLoading] wird dann ausgeführt;
- [errorLoading], was signalisiert, dass eine Fehlermeldung angezeigt werden muss. Die Funktion [mShowErrorLoading] wird dann ausgeführt;
- die [nuxt]-Seiten:
- zeigen die Lademeldung an, indem sie das Ereignis [‘loading’, true] auf dem Ereignisbus auslösen;
- blenden die Lademeldung aus, indem sie das Ereignis [‘loading’, false] auf dem Ereignisbus auslösen;
- zeigen eine Fehlermeldung an, indem sie das Ereignis [‘errorLoading’, true] auf dem Ereignisbus auslösen;
- die Fehlermeldung ausblenden, indem das Ereignis [‘errorLoading’, false] auf dem Ereignisbus ausgelöst wird;
15.12.2. [error]
Das [error]-Layout zeigt eine Systemfehlermeldung an (wird nicht vom Entwickler verwaltet):
<!-- 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 rose -->
<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>
15.13. Die vom [nuxt]-Server bereitgestellte [index]-Seite

Die Seite [index.vue] ist insofern einzigartig, als sie nur über den [nuxt]-Server erreichbar ist. Dem Benutzer wird kein Link bereitgestellt, um über den [nuxt]-Client darauf zuzugreifen. Der Code lautet wie folgt:
<!-- page principale -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<b-alert slot="right" show variant="warning">Initialisation de la session avec le serveur de calcul de l'impôt : {{ result }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'InitSession',
// components used
components: {
Layout,
Navigation
},
// asynchronous data
async asyncData(context) {
// log
console.log('[index asyncData started]')
try {
// start a jSON session
const dao = context.app.$dao()
const response = await dao.initSession()
// log
console.log('[index asyncData response=]', response)
// retrieve session cookie PHP for future requests
const phpSessionCookie = dao.getPhpSessionCookie()
// we store the PHP session cookie in the [nuxt] session
context.store.commit('replace', { phpSessionCookie })
// was there a mistake?
if (response.état !== 700) {
// the error is in response.réponse
throw new Error(response.réponse)
}
// note that the jSON session has started
context.store.commit('replace', { jsonSessionStarted: true })
// we return the result
return { result: '[succès]' }
} catch (e) {
// log
console.log('[index asyncData error=]', e)
// note that session jSON has not started
context.store.commit('replace', { jsonSessionStarted: false })
// we report the error
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// save the blind
const session = context.app.$session()
session.save(context)
// log
console.log('[index asyncData finished]')
}
},
// life cycle
beforeCreate() {
console.log('[index beforeCreate]')
},
created() {
console.log('[index created]')
},
beforeMount() {
console.log('[index beforeMount]')
},
mounted() {
console.log('[index mounted]')
// customer only
if (this.showErrorLoading) {
console.log('[index mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
- Zeile 7: Die Seite zeigt das Ergebnis [result] einer asynchronen Anfrage an (Zeilen 46 und 51);
- Zeile 31: Der asynchrone Vorgang besteht darin, eine JSON-Sitzung mit dem Steuerberechnungsserver zu öffnen;
- Zeile 25: Wir wissen, dass bei einer direkten Anfrage der Seite vom [nuxt]-Server die Funktion [asyncData] nur vom Server und nicht vom [nuxt]-Client ausgeführt wird, der erst startet, sobald der Browser die Antwort vom [nuxt]-Server erhalten hat;
- Zeile 30: Wir rufen die [dao]-Schicht aus dem [nuxt]-Serverkontext ab;
- Zeile 35: Wenn der Server noch keine Anfrage an den Steuerberechnungsserver gestellt hat, erhält er sein erstes PHP-Sitzungscookie; andernfalls erhält er das letzte PHP-Sitzungscookie, das er erhalten hat (siehe den Code für die [dao]-Schicht des [nuxt]-Servers im verlinkten Abschnitt);
- Zeile 37: Dieses PHP-Sitzungs-Cookie wird im Speicher abgelegt;
- Zeilen 39–42: Wir prüfen, ob der Vorgang erfolgreich war. Falls nicht, wird eine Ausnahme ausgelöst, die von dem [catch] in Zeile 47 abgefangen wird;
- Zeile 44: Wir vermerken im Speicher, dass die JSON-Sitzung mit dem PHP-Server begonnen hat;
- Zeile 46: Das Ergebnis [result] wird zurückgegeben und in Zeile 7 angezeigt;
- Zeilen 47–54: Behandlung etwaiger Ausnahmen. Diese können zweierlei Art sein:
- Der HTTP-Vorgang in Zeile 31 ist aufgrund eines Kommunikationsfehlers zwischen dem [nuxt]-Server und dem PHP-Server fehlgeschlagen;
- die HTTP-Operation in Zeile 31 war erfolgreich, aber das empfangene Ergebnis meldete einen Fehler (Zeilen 39–42);
- Zeile 51: Wir stellen fest, dass die JSON-Sitzung mit dem PHP-Server nicht gestartet wurde;
- Zeile 53: Das Ergebnis [result] wird zurückgegeben und in Zeile 7 angezeigt. Zusätzlich werden die Eigenschaften [showErrorLoading] und [errorLoadingMessage] gesetzt, die der [nuxt]-Client verwendet, um eine Fehlermeldung anzuzeigen, wenn er die vom [nuxt]-Server gesendete Seite empfängt (Zeilen 72–79);
- Zeilen 54–60: Code, der in allen Fällen (Erfolg oder Fehler) ausgeführt wird;
- Zeile 56: Wir rufen die [nuxt]-Sitzung aus dem [nuxt]-Serverkontext ab;
- Zeile 57: Wir speichern sie;
- Zeilen 63–68: Sobald die Funktion [asyncData] beendet ist, führt der [nuxt]-Server die Funktionen [beforeCreate] und [create] aus;
Hinweis: Die Ausführung der Seite [index] durch den [nuxt]-Server kann fehlschlagen, beispielsweise wenn der Steuerberechnungsserver beim Start der [nuxt]-Anwendung nicht läuft:

In diesem Fall besteht die einzige Lösung darin, zuerst den Steuerberechnungsserver und dann die [nuxt]-Anwendung selbst zu starten, da das Navigationsmenü keine Option bietet, eine JSON-Sitzung mit dem Steuerberechnungsserver zu initiieren;
15.14. Die vom [nuxt]-Client ausgeführte [index]-Seite
Die [index]-Seite wird vom [nuxt]-Client erst dann ausgeführt, wenn der [nuxt]-Server sie an den Client gesendet hat. Der Server hat die [result]-Informationen sowie gegebenenfalls [showErrorLoading] und [errorLoadingMessage] gesendet.
Wir wissen, dass die [asyncData]-Funktion nicht ausgeführt wird. Damit bleiben die Lebenszyklusfunktionen, insbesondere die [mounted]-Funktion:
mounted() {
console.log('[index mounted]')
// client seulement
if (this.showErrorLoading) {
console.log('[index mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
- Der [nuxt]-Client fügt automatisch das Element [result] und, falls zutreffend, die Elemente [showErrorLoading] und [errorLoadingMessage], die ihm vom [nuxt]-Server gesendet wurden, in die Seiteneigenschaften ein:
- Die Eigenschaft [result] wird in Zeile 7 angezeigt;
- Die Eigenschaften [showErrorLoading, errorLoadingMessage] werden von der Methode [mounted] verwendet: In Zeile 4 wird die Eigenschaft [showErrorLoading] überprüft. Ist sie wahr, wird in Zeile 6 der [nuxt]-Ereignisbus des Clients verwendet, um zu signalisieren, dass eine Fehlermeldung angezeigt werden muss;
- das in Zeile 6 ausgelöste [errorLoading]-Ereignis wird von der Seite [layouts/default] abgefangen, die im verlinkten Abschnitt beschrieben wird;
15.15. Die vom [nuxt]-Server ausgeführte Seite [authentication]
Die Seite [authentication] ist für die Authentifizierung eines Benutzers beim Steuerberechnungsserver zuständig. Ihr Code lautet wie folgt:
<!-- page d’authentification -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<b-alert slot="right" show variant="warning">Authentification auprès du serveur de calcul de l'impôt : {{ result }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Authentification',
// components used
components: {
Layout,
Navigation
},
// asynchronous data
async asyncData(context) {
// log
console.log('[authentification asyncData started]')
if (process.client) {
// start waiting for customer [nuxt]
context.app.$eventBus().$emit('loading', true)
// no error
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// authenticate to the server
const dao = context.app.$dao()
const response = await dao.authentifierUtilisateur('admin', 'admin')
// log
console.log('[authentification asyncData response=]', response)
// result
const userAuthenticated = response.état === 200
// we note whether the user is authenticated or not
context.store.commit('replace', { userAuthenticated })
// save the store in the [nuxt] session
const session = context.app.$session()
session.save(context)
// authentication error?
if (!userAuthenticated) {
// the error is in response.réponse
throw new Error(response.réponse)
}
// we return the result
return { result: '[succès]' }
} catch (e) {
// we report the error
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[authentification asyncData finished]')
if (process.client) {
// end customer waiting [nuxt]
context.app.$eventBus().$emit('loading', false)
}
}
},
// life cycle
beforeCreate() {
console.log('[authentification beforeCreate]')
},
created() {
console.log('[authentification created]')
},
beforeMount() {
console.log('[authentification beforeMount]')
},
mounted() {
console.log('[authentification mounted]')
// customer only
if (this.showErrorLoading) {
console.log('[authentification mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
- Zeile 7: Die Seite zeigt das Ergebnis [result] der asynchronen Anfrage [asyncData] aus den Zeilen 25–65 an;
- Zeilen 28–33: Der Server führt diese für den Client [nuxt] bestimmten Zeilen nicht aus;
- Zeile 36: Die [dao]-Schicht wird vom [nuxt]-Server abgerufen;
- Zeile 37: Wir authentifizieren uns beim Steuerberechnungsserver mit den Test-Anmeldedaten [admin, admin], die als einzige vom Steuerberechnungsserver akzeptiert werden;
- Zeile 41: Der Authentifizierungsvorgang ist nur erfolgreich, wenn der Antwortstatus 200 lautet;
- Zeile 43: Wir setzen die Eigenschaft [userAuthenticated] im Store;
- Zeilen 44–46: Der Store wird in der [nuxt]-Sitzung gespeichert;
- Zeilen 48–51: Wenn die Authentifizierung fehlgeschlagen ist, wird eine Ausnahme mit der vom Steuerberechnungsserver gesendeten Fehlermeldung ausgelöst;
- ansonsten wird in Zeile 53 ein Erfolgsergebnis zurückgegeben, das in Zeile 7 angezeigt wird;
- Zeilen 54–57: Im Falle eines Fehlers werden drei Seiteneigenschaften gesetzt: [result], [showErrorLoading] und [errorLoadingMessage]. Die Eigenschaft [result] wird in Zeile 7 angezeigt. Die drei Eigenschaften werden an den [nuxt]-Client gesendet;
- Zeilen 60–63: werden vom [nuxt]-Server nicht ausgeführt;
- Sobald [asyncData] sein Ergebnis zurückgegeben hat, wird es in Zeile 7 angezeigt. Anschließend werden die Methoden [beforeCreate] (Zeilen 67–69) und [created] (Zeilen 70–72) ausgeführt;
- Das war's;
Hinweis: Die Seite [authentification] wird möglicherweise nicht auf dem [nuxt]-Server ausgeführt, beispielsweise wenn die JSON-Sitzung mit dem Steuerberechnungsserver nicht initialisiert wurde. Dies kann wie folgt erfolgen:
- Löschen Sie das PHP-Session-Cookie aus Ihrem Browser (um von vorne zu beginnen):

- Starten Sie die [nuxt]-Anwendung, während der Berechnungsserver noch nicht gestartet wurde: Sie erhalten eine Fehlermeldung;
- Starten Sie den Steuerberechnungsserver;
- Geben Sie die URL [/authentication] direkt in die Adressleiste des Browsers ein:

In diesem Fall besteht die einzige Lösung darin, die Seite [index] erneut zu laden.
15.16. Die vom [nuxt]-Client ausgeführte [authentication]-Seite
Schauen wir uns den Code der Seite noch einmal an:
<!-- page d’authentification -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<b-alert slot="right" show variant="warning">Authentification auprès du serveur de calcul de l'impôt : {{ result }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'Authentification',
// components used
components: {
Layout,
Navigation
},
// asynchronous data
async asyncData(context) {
// log
console.log('[authentification asyncData started]')
if (process.client) {
// start waiting for customer [nuxt]
context.app.$eventBus().$emit('loading', true)
// no error
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// authenticate to the server
const dao = context.app.$dao()
const response = await dao.authentifierUtilisateur('admin', 'admin')
// log
console.log('[authentification asyncData response=]', response)
// result
const userAuthenticated = response.état === 200
// we note whether the user is authenticated or not
context.store.commit('replace', { userAuthenticated })
// save the store in the [nuxt] session
const session = context.app.$session()
session.save(context)
// authentication error?
if (!userAuthenticated) {
// the error is in response.réponse
throw new Error(response.réponse)
}
// we return the result
return { result: '[succès]' }
} catch (e) {
// we report the error
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[authentification asyncData finished]')
if (process.client) {
// end customer waiting [nuxt]
context.app.$eventBus().$emit('loading', false)
}
}
},
// life cycle
beforeCreate() {
console.log('[authentification beforeCreate]')
},
created() {
console.log('[authentification created]')
},
beforeMount() {
console.log('[authentification beforeMount]')
},
mounted() {
console.log('[authentification mounted]')
// customer only
if (this.showErrorLoading) {
console.log('[authentification mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
Es gibt zwei Szenarien, in denen die [authentication]-Seite vom [nuxt]-Client ausgeführt wird:
- Der [nuxt]-Client wird ausgeführt, nachdem der [nuxt]-Server die [Authentifizierungs]-Seite an den Browser des [nuxt]-Clients gesendet hat;
- der [nuxt]-Client, weil der Benutzer auf den Link [Authentication] im Navigationsmenü geklickt hat:

Betrachten wir zunächst das erste Szenario. In diesem Fall führt der [nuxt]-Client die Funktion [asyncData] nicht aus. Er bindet das Element [result] und gegebenenfalls die Elemente [showErrorLoading] und [errorLoadingMessage], die ihm vom [nuxt]-Server gesendet wurden, in die Eigenschaften der Seite ein:
- Die Eigenschaft [result] wird in Zeile 7 angezeigt;
- die Eigenschaften [showErrorLoading] und [errorLoadingMessage] werden von der Methode [mounted] verwendet: In Zeile 79 wird die Eigenschaft [showErrorLoading] überprüft. Ist sie wahr, wird in Zeile 81 der Ereignisbus des [nuxt]-Clients verwendet, um zu signalisieren, dass eine Fehlermeldung angezeigt werden muss;
Der Mechanismus zur Anzeige der Fehlermeldung wurde für die [index]-Seite im Abschnitt „Links“ erläutert.
Fall 2 tritt ein, wenn der [nuxt]-Client ausgeführt wird, nachdem der Benutzer auf den Link [Authentication] geklickt hat. In diesem Fall läuft der [nuxt]-Client unabhängig und nicht nach dem [nuxt]-Server. Anschließend wird die Funktion [asyncData] ausgeführt. Wir geben hier nur die Details wieder, die sich von den Erläuterungen zur vom [nuxt]-Server ausgeführten Seite unterscheiden:
- Zeilen 28–33: Der [nuxt]-Client fordert an, dass die Lademeldung angezeigt und jede zuvor angezeigte Fehlermeldung gelöscht wird;
- Zeile 36: Hier wird nun die [dao]-Schicht des [nuxt]-Clients abgerufen;
- Zeilen 60–63: Der [nuxt]-Client fordert an, dass die Lademeldung entfernt wird;
- Sobald [asyncData] abgeschlossen ist, wird der Seitenlebenszyklus fortgesetzt. Die Funktion [mounted] in den Zeilen 76–83 wird ausgeführt. Wenn ein Fehler aufgetreten ist, wird die Fehlermeldung angezeigt;
Hinweis: Um einen Fehler auszulösen, befolgen Sie die am Ende des Abschnitts „Links“ beschriebene Vorgehensweise für den [nuxt]-Server, aber anstatt die [authentication]-Seite durch Eingabe ihrer URL in die Adressleiste aufzurufen, verwenden Sie den Link [Authentication] im Navigationsmenü. Dadurch wird der [nuxt]-Client ausgeführt.
15.17. Die Seite [get-admindata]
Der Code für die Seite [get-admindata] lautet wie folgt:
<!-- vue get-admindata -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message -->
<b-alert slot="right" show variant="secondary"> Demande de [adminData] au serveur de calcul de l'impôt : {{ result }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'GetAdmindata',
// components used
components: {
Layout,
Navigation
},
// asynchronous data
async asyncData(context) {
// log
console.log('[get-admindata asyncData started]')
if (process.client) {
// start waiting
context.app.$eventBus().$emit('loading', true)
// no error
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// the data [admindata] is requested
const response = await context.app.$dao().getAdminData()
// log
console.log('[get-admindata asyncData response=]', response)
// result
const adminData = response.état === 1000 ? response.réponse : ''
// put the data in the store
context.store.commit('replace', { adminData })
// save the store in the [nuxt] session
const session = context.app.$session()
session.save(context)
// was there a mistake?
if (!adminData) {
// the error is in response.réponse
throw new Error(response.réponse)
}
// return the value received
return { result: adminData }
} catch (e) {
// we report the error
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[get-admindata asyncData finished]')
if (process.client) {
// end waiting
context.app.$eventBus().$emit('loading', false)
}
}
},
// life cycle
beforeCreate() {
console.log('[get-admindata beforeCreate]')
},
created() {
console.log('[get-admindata created]')
},
beforeMount() {
console.log('[get-admindata beforeMount]')
},
mounted() {
console.log('[get-admindata mounted]')
// customer
if (this.showErrorLoading) {
console.log('[get-admindata mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
Diese Seite ist der [authentication]-Seite sehr ähnlich. Die Erläuterungen sind dieselben, unabhängig davon, ob sie vom [nuxt]-Server oder vom [nuxt]-Client ausgeführt wird. Beachten Sie jedoch, dass in Zeile 7 nicht wie zuvor Erfolg oder Misserfolg angezeigt wird, sondern der Wert der vom Steuerberechnungsserver empfangenen Daten (Zeile 52):

Das obige Ergebnis wird sowohl auf dem Server als auch auf dem [nuxt]-Client erzielt. Um einen Fehler auszulösen, rufen Sie die Seite [get-admindata] auf – entweder über den Server oder den [nuxt]-Client –, ohne authentifiziert zu sein:

15.18. Die Seite [fin-session]
Der Seitencode lautet wie folgt:
<!-- page principale -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<b-alert slot="right" show variant="warning">Fin de la session avec le serveur de calcul de l'impôt : {{ result }} </b-alert>
</Layout>
</template>
<script>
/* eslint-disable no-console */
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
export default {
name: 'FinSession',
// components used
components: {
Layout,
Navigation
},
// asynchronous data
async asyncData(context) {
// log
console.log('[fin-session asyncData started]')
// customer case [nuxt]
if (process.client) {
// start waiting
context.app.$eventBus().$emit('loading', true)
// no error
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// a new session PHP is requested from the tax calculation server
const dao = context.app.$dao()
const response = await dao.finSession()
// log
console.log('[fin-session asyncData response=]', response)
// was there a mistake?
if (response.état !== 400) {
// the error is in response.réponse
throw new Error(response.réponse)
}
// the server has sent a new session cookie PHP
// we retrieve it for both the server and the nuxt client
// if this code is executed by the [nuxt] client, the PHP session cookie must be set in the nuxt session
// so that the [plgDao] plugin on the [nuxt] server can retrieve it and initialize the [dao] layer with
// if this code is executed by the [nuxt] server, the PHP session cookie must be set in the nuxt session
// so that the client routing [nuxt] can retrieve it and pass it to the browser
const phpSessionCookie = dao.getPhpSessionCookie()
// we note in the store that the session jSON has been started and we store the session cookie PHP
context.store.commit('replace', { jsonSessionStarted: true, phpSessionCookie, userAuthenticated: false, adminData: '' })
// save the store in the [nuxt] session
const session = context.app.$session()
session.save(context)
// we return the result
return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
} catch (e) {
// log
console.log('[fin-session asyncData error=]', e)
// report the error
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[fin-session asyncData finished]')
if (process.client) {
// end waiting
context.app.$eventBus().$emit('loading', false)
}
}
},
// life cycle
beforeCreate() {
console.log('[fin-session beforeCreate]')
},
created() {
console.log('[fin-session created]')
},
beforeMount() {
console.log('[fin-session beforeMount]')
},
mounted() {
console.log('[fin-session mounted]')
// customer only
if (this.showErrorLoading) {
console.log('[fin-session mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
Der Code ist dem auf den vorherigen Seiten sehr ähnlich, und die Erklärungen sind dieselben. Es gibt nur einen Punkt zu beachten: Der asynchrone Vorgang in Zeile 38 bewirkt, dass der Steuerberechnungsserver ein neues PHP-Sitzungs-Cookie sendet. Die Anweisungen zum Umgang mit diesem Cookie unterscheiden sich je nachdem, ob der Server oder der [nuxt]-Client diesen Code ausführt.
Beginnen wir mit dem [nuxt]-Server:
- Zeile 37: Hier wird die [dao]-Schicht des [nuxt]-Servers instanziiert. Erinnern wir uns an den Code für ihren Konstruktor:
// constructeur
constructor(axios, phpSessionCookie) {
// bibliothèque axios
this.axios = axios
// valeur du cookie de session
this.phpSessionCookie = phpSessionCookie
// nom du cookie de session du serveur PHP
this.phpSessionCookieName = 'PHPSESSID'
}
In Zeile 1 sehen wir, dass der Konstruktor das aktuelle PHP-Sitzungs-Cookie benötigt – das zuletzt empfangene, sei es vom Server oder vom [nuxt]-Client;
- Zeile 52: Der [nuxt]-Server ruft das Cookie für die neue PHP-Sitzung oder das alte Cookie ab, falls der Vorgang zum Beenden der Sitzung fehlgeschlagen ist;
- Zeile 54: Das PHP-Sitzungs-Cookie wird im Speicher abgelegt und dann in den Zeilen 56–57 in der [nuxt]-Sitzung gespeichert;
- Nach dem Server ist es der [nuxt]-Client, der die [end-session]-Seite mit den vom Server gesendeten Daten ausführt. Wir wissen, dass er die [asyncData]-Funktion nicht ausführen wird;
- Letztendlich wissen wir, nachdem der Server und der [nuxt]-Client ihre Arbeit beendet haben, dass sich das für die Kommunikation mit dem Steuerberechnungsserver erforderliche PHP-Cookie in der [nuxt]-Sitzung befindet;
Die Tatsache, dass sich das PHP-Cookie in der [nuxt]-Sitzung befindet, reicht für den Server aus, da seine [dao]-Schicht es dort abrufen wird. Im Plugin [server/plgDao], das die [dao]-Schicht des Servers initialisiert, haben wir geschrieben:
/* eslint-disable no-console */
// on crée un point d'accès à la couche [Dao]
import Dao from '@/api/server/Dao'
export default (context, inject) => {
// configuration axios
context.$axios.defaults.timeout = context.env.timeout
context.$axios.defaults.baseURL = context.env.baseURL
// on récupère le cookie de session
const store = context.app.$session().value.store
const phpSessionCookie = store ? store.phpSessionCookie : ''
console.log('session=', context.app.$session().value, 'phpSessionCookie=', phpSessionCookie)
// instanciation de la couche [dao]
const dao = new Dao(context.$axios, phpSessionCookie)
// injection d'une fonction [$dao] dans le contexte
inject('dao', () => dao)
// log
console.log('[fonction server $dao créée]')
}
- Zeile 13: Die [dao]-Schicht des [nuxt]-Servers wird mit dem PHP-Session-Cookie instanziiert, das aus der [nuxt]-Session stammt (Zeilen 9–10);
Beim [nuxt]-Client sieht die Sache anders aus. Nicht der Client sendet das Cookie, sondern der Browser führt es aus. Dieser Browser kennt jedoch das Cookie für die neue PHP-Sitzung nicht, die der [nuxt]-Server empfangen hat. Wenn wir die Links im Navigationsmenü [3] verwenden:

erhält der Steuerberechnungsserver ein veraltetes PHP-Sitzungs-Cookie vom Browser und antwortet, dass mit diesem Cookie keine JSON-Sitzung verknüpft ist. Wir müssen einen Weg finden, das neue PHP-Sitzungs-Cookie an den Browser weiterzugeben.
Dazu können wir Routing-Middleware verwenden:

Das Skript [client/routing] ist die Routing-Middleware, die in der Datei [nuxt.config] deklariert ist:
// router
router: {
// application URL root
base: '/nuxt-12/',
// routing middleware
middleware: ['routing']
},
Das Skript [middleware/routing] lautet wie folgt:
/* eslint-disable no-console */
// on importe le middleware du client
import clientRouting from './client/routing'
export default function(context) {
// qui exécute ce code ?
console.log('[middleware], process.server', process.server, ', process.client=', process.client)
if (process.client) {
// routage client
clientRouting(context)
}
}
- Zeilen 9–12: Wir leiten den Client nur mithilfe einer in Zeile 4 importierten Funktion weiter;
Das Skript [middleware/client/routing] lautet wie folgt:
/* eslint-disable no-console */
export default function(context) {
// who executes this code?
console.log('[middleware client], process.server', process.server, ', process.client=', process.client)
// management of the PHP session cookie in the browser
// the browser's PHP session cookie must be identical to the one found in the nuxt session
// acion [fin-session] receives a new cookie PHP (server as nuxt client)
// if the server receives it, the client must pass it on to the browser
// for its own exchanges with the PHP server
// this is customer routing
// retrieve the session cookie PHP
const phpSessionCookie = context.store.state.phpSessionCookie
if (phpSessionCookie) {
// if it exists, we assign the PHP session cookie to the browser
document.cookie = phpSessionCookie
}
}
Kehren wir zu der Situation unmittelbar nach der Ausführung der Seite [fin-session] durch den [nuxt]-Server zurück:

Wenn Sie auf einen der Links im [3]-Menü klicken, übernimmt der [nuxt]-Client. Da ein Seitenwechsel stattfindet, wird das Routing-Skript des Clients ausgeführt:
- Zeile 13: Das PHP-Session-Cookie wird im [nuxt]-Anwendungsspeicher gefunden;
- Zeile 14: Wenn es nicht leer ist, wird es an den Browser gesendet (Zeile 16). Ab diesem Zeitpunkt verfügt der Browser des [nuxt]-Clients über das richtige PHP-Session-Cookie;
Das Skript [client/routing] wird jedes Mal ausgeführt, wenn der [nuxt]-Client die Seite wechselt. Der Code des Skripts funktioniert unabhängig von der Zielseite: Im Wesentlichen sendet er dem Browser meistens ein PHP-Session-Cookie, das dieser bereits hat, außer in zwei Fällen:
- Unmittelbar nach dem Start der Anwendung führt der [nuxt]-Server die [index]-Seite aus und erhält ein erstes PHP-Sitzungs-Cookie, über das der Browser des [nuxt]-Clients nicht verfügt;
- wenn der [nuxt]-Server die [end-session]-Seite wie gerade erläutert ausführt;
Betrachten wir nun den Fall, in dem die Seite [end-session] nur vom [nuxt]-Client ausgeführt wird, weil der Benutzer auf den entsprechenden Link im Navigationsmenü geklickt hat. Nun ist es der [nuxt]-Client, der die Funktion [asyncData] ausführt:
try {
// a new session PHP is requested from the tax calculation server
const dao = context.app.$dao()
const response = await dao.finSession()
// log
console.log('[fin-session asyncData response=]', response)
// was there a mistake?
if (response.état !== 400) {
// the error is in response.réponse
throw new Error(response.réponse)
}
// the server has sent a new session cookie PHP
// we retrieve it for both the server and the nuxt client
// if this code is executed by the [nuxt] client, the PHP session cookie must be set in the nuxt session
// so that the [plgDao] plugin on the [nuxt] server can retrieve it and initialize the [dao] layer with
// if this code is executed by the [nuxt] server, the PHP session cookie must be set in the nuxt session
// so that the client routing [nuxt] can retrieve it and pass it to the browser
const phpSessionCookie = dao.getPhpSessionCookie()
// we note in the store that the session jSON has been started and we store the session cookie PHP
context.store.commit('replace', { jsonSessionStarted: true, phpSessionCookie, userAuthenticated: false, adminData: '' })
// save the store in the [nuxt] session
const session = context.app.$session()
session.save(context)
// we return the result
return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
} catch (e) {
// log
console.log('[fin-session asyncData error=]', e)
// report the error
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[fin-session asyncData finished]')
if (process.client) {
// end waiting
context.app.$eventBus().$emit('loading', false)
}
}
- Zeile 3: Hier wird die [dao]-Schicht des [nuxt]-Clients abgerufen;
- Zeile 18: Das vom [dao]-Layer des [nuxt]-Clients abgerufene PHP-Session-Cookie wird gespeichert, in den Speicher abgelegt (Zeile 20) und anschließend in der [nuxt]-Session gespeichert (Zeilen 22–23);
- Von da an funktioniert alles einwandfrei, da wir wissen, dass die [dao]-Schicht des [nuxt]-Servers das PHP-Sitzungs-Cookie aus der [nuxt]-Sitzung abruft;
15.19. Ausführung
Um dieses Beispiel auszuführen, müssen Sie zunächst das [nuxt]-Sitzungs-Cookie und das PHP-Cookie aus dem Browser löschen, in dem der [nuxt]-Client läuft, um mit einer sauberen Basis zu beginnen. Nachfolgend finden Sie ein Beispiel für den Chrome-Browser:

15.20. Fazit
Dieses Beispiel war besonders komplex. Es vereinte Kenntnisse aus früheren Beispielen: Speicherung der Persistenz in einer [nuxt]-Sitzung, Plugins zur Funktionsinjektion, Routing-Middleware und Fehlerbehandlung für asynchrone Operationen. Die Komplexität wurde dadurch erhöht, dass wir dem Benutzer ermöglichen wollten, sowohl die Links im Navigationsmenü zu nutzen als auch URLs manuell einzugeben, ohne dass die Anwendung dabei abstürzt. Um dies zu erreichen, mussten wir untersuchen, wie sich jede Seite verhält, je nachdem, ob sie vom Client oder vom [nuxt]-Server ausgeführt wird.
Diese Konsistenz im Verhalten von Client und [Nuxt]-Server ist nicht zwingend erforderlich. Betrachten wir das folgende häufige Szenario:
- die erste Seite vom [nuxt]-Server bereitgestellt wird;
- alle nachfolgenden Seiten vom [nuxt]-Client bereitgestellt werden, der dann im [SPA]-Modus arbeitet;
Dennoch müssen Sie auch in diesem Fall überprüfen, wie alle Seiten gerendert werden, wenn sie vom [nuxt]-Server ausgeführt werden, da dies das ist, was Suchmaschinen sehen, wenn sie diese Seiten anfordern.