Skip to content

13. Esempio [nuxt-10]: asyncData e caricamento

La funzione [asyncData] in una pagina consente di caricare in modo asincrono dati spesso esterni. [nuxt] attende il completamento della funzione [asyncData] prima di avviare il ciclo di vita della pagina. La pagina viene quindi visualizzata solo una volta ottenuti i dati esterni. Viene eseguita sia dal server che dal client secondo le seguenti regole:

  • quando la pagina viene richiesta direttamente al server, solo il server esegue la funzione [asyncData];
  • successivamente, durante la navigazione del client, solo il client esegue la funzione [asyncData];

In definitiva, solo uno dei due, client o server, esegue la funzione. Inoltre, quando è il client a eseguire la funzione [asyncData], [nuxt] visualizza una barra di avanzamento che può essere configurata.

La funzione [asyncData] consente di fornire ai motori di ricerca pagine con i relativi dati, rendendole così più significative.

L’esempio [nuxt-10] si ottiene inizialmente copiando il progetto [nuxt-01]:

Image

Solo la pagina [page1] subisce modifiche.

13.1. La pagina [page1]

Il codice della pagina [page1] è il seguente:


<!-- vista n. 1 -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigazione -->
    <Navigation slot="left" />
    <!-- messaggio-->
    <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',
  // componenti utilizzati
  components: {
    Layout,
    Navigation
  },
  // dati asincroni
  asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // si restituisce una promessa
    return new Promise(function(resolve, reject) {
      // si simula una funzione asincrona
      setTimeout(function () {
        // si restituisce il risultato in modo asincrono - in questo caso un numero casuale
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
        // log
        console.log('[page1 asyncData finished]')
      }, 5000)
    })
  },

  // ciclo di vita
  beforeCreate() {
    console.log('[page1 beforeCreate]')
  },
  created() {
    console.log('[page1 created]')
  },
  beforeMount() {
    console.log('[page1 beforeMount]')
  },
  mounted() {
    console.log('[page1 mounted]')
  }
}
</script>
  • righe 26-39: la funzione [asyncData]. Abbiamo già esaminato questa funzione (cfr. paragrafo link). Viene eseguita prima del ciclo di vita della pagina. Per questo motivo, non è possibile utilizzare la parola chiave [this] all’interno della funzione;
  • riga 30: deve restituire una promessa [Promise] oppure utilizzare la sintassi async / await;
  • righe 32-37: la funzione asincrona della promessa viene simulata con un'attesa di 5 secondi (riga 37);
  • riga 34: il risultato della funzione asincrona viene restituito sotto forma di oggetto {result :...}. L'oggetto asincrono restituito dalla funzione [asyncData] viene integrato nell'oggetto [data] della pagina. Ecco perché l’oggetto [result] è disponibile alla riga 7 del template, anche se la pagina non aveva definito alcun oggetto [data];

13.2. Configurazione della barra di avanzamento di [asyncData]

Quando la pagina [page1] è la destinazione di una navigazione all’interno del client (modalità SPA), il client esegue la funzione [asyncData] e [nuxt] visualizza quindi una barra di avanzamento che nasconde quando la funzione [asyncData] ha restituito il proprio risultato. La proprietà [loading] del file [nuxt.config.js] consente di configurare questa barra:


loading: {
    color: 'blue',
    height: '5px',
    throttle: 200,
    continuous: true
},

Per impostazione predefinita, l’immagine di attesa di [nuxt] è una barra di avanzamento che occupa l’intera larghezza della pagina. Questa barra ha un colore e uno spessore. La linea colorata cresce progressivamente dallo 0% al 100% della sua dimensione, quindi più o meno velocemente a seconda della durata dell’attesa.

  • riga 2: imposta il colore della barra di avanzamento;
  • riga 3: imposta lo spessore della barra in pixel;
  • riga 4: [throttle] è il ritardo in millisecondi prima che l’animazione abbia inizio. Ciò consente di evitare la visualizzazione di immagini di animazione quando la funzione [asyncData] restituisce rapidamente il proprio risultato;
  • riga 5: [continuous] definisce il comportamento dell’animazione della barra di avanzamento. Per impostazione predefinita, la barra cresce progressivamente dallo 0% al 100% della sua dimensione, più o meno velocemente a seconda della durata dell’attesa. Con [continuous:true], la barra colorata cresce a velocità costante dallo 0 al 100% della sua dimensione, per poi ricominciare finché la funzione [asyncData] non ha restituito il risultato;

13.3. Exécution

Avviamo l’applicazione, quindi richiediamo manualmente al server la pagina [page1]:

Image

I log sono i seguenti:

Image

  • si nota che solo il server [1] ha eseguito la funzione [asyncData] e lo ha fatto prima del ciclo della pagina;

Ora esaminiamo la pagina inviata dal server (codice sorgente):


<!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-10/">
  <link rel="preload" href="/nuxt-10/_nuxt/runtime.js" as="script">
  <link rel="preload" href="/nuxt-10/_nuxt/commons.app.js" as="script">
  <link rel="preload" href="/nuxt-10/_nuxt/vendors.app.js" as="script">
  <link rel="preload" href="/nuxt-10/_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-10] : asyncData et loading</h4>
              </div>
            <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-10/" target="_self" class="nav-link">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-10/page1" target="_self" class="nav-link active nuxt-link-active">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-10/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" class="alert alert-primary"> Page 1 -- result=3 </div></div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>window.__NUXT__ = (function (a, b, c) {
  return {
    layout: "default", data: [{ result: 3 }], error: null, serverRendered: true,
    logs: [
      { date: new Date(1574939615256), args: ["[page1 asyncData started]"], type: a, level: b, tag: c },
      { date: new Date(1574939620263), args: ["[page1 asyncData finished]"], type: a, level: b, tag: c },
      { date: new Date(1574939620285), args: ["[page1 beforeCreate]"], type: a, level: b, tag: c },
      { date: new Date(1574939620287), args: ["[page1 created]"], type: a, level: b, tag: c }
    ]
  }
    }("log", 2, ""));</script>
  <script src="/nuxt-10/_nuxt/runtime.js" defer></script>
  <script src="/nuxt-10/_nuxt/commons.app.js" defer></script>
  <script src="/nuxt-10/_nuxt/vendors.app.js" defer></script>
  <script src="/nuxt-10/_nuxt/app.js" defer></script>
</body>
</html>
  • riga 55: si nota che il server ha inviato al client un array [data] contenente l’oggetto [result:3], che è stato integrato nell’oggetto [data] della pagina [page1] del server. Affinché il client possa fare lo stesso e quindi visualizzare la stessa pagina del server, quest’ultimo gli trasmette l’oggetto [result]. Si ricorda che il client non eseguirà la funzione [asyncData]. Si limiterà semplicemente a utilizzare i dati calcolati dal server;

Ora passiamo dalla pagina [Home] alla pagina [Page 1] utilizzando il menu di navigazione:

Image

  • nella pagina [1] compare la barra di avanzamento;

Dopo 5 secondi, si visualizza la pagina [Page 1]:

Image

I log sono i seguenti:

Image

Si nota che il client ha eseguito la funzione [asyncData] prima del ciclo di vita della pagina.