Scorrere pagine di dati con for, while e do...while in JavaScript

by Anastasia P.
SHARE
Scorrere pagine di dati con for, while e do...while in JavaScript
© Guida-HTML5.it

Introduzione

Quando un’applicazione deve elaborare molti dati, spesso le informazioni non arrivano tutte insieme. Un’API, per esempio, può restituire una pagina alla volta: ogni risposta contiene un gruppo di elementi e un riferimento alla pagina successiva. In questo scenario i cicli JavaScript sono fondamentali per automatizzare il caricamento e l’elaborazione dei risultati.

In questo tutorial realizzeremo un piccolo programma che simula il recupero di prodotti da un’API paginata. Useremo tre approcci diversi:

  • for, quando conosciamo il numero massimo di pagine da visitare;
  • while, quando continuiamo finché esiste una pagina successiva;
  • do...while, quando vogliamo eseguire almeno una richiesta prima di controllare la condizione.

L’esempio usa una funzione asincrona che simula una richiesta di rete. La stessa struttura può essere adattata a fetch() e a un’API reale.

Codice completo

// Dati organizzati in pagine, come potrebbe fare un´API reale
const pagine = [
  {
    dati: [
      { nome: "Tastiera", categoria: "accessori", prezzo: 49 },
      { nome: "Mouse", categoria: "accessori", prezzo: 25 }
    ],
    paginaSuccessiva: 1
  },
  {
    dati: [
      { nome: "Monitor", categoria: "schermi", prezzo: 180 },
      { nome: "Webcam", categoria: "accessori", prezzo: 70 }
    ],
    paginaSuccessiva: 2
  },
  {
    dati: [
      { nome: "Microfono", categoria: "audio", prezzo: 95 }
    ],
    paginaSuccessiva: null
  }
];

// Simula una richiesta asincrona a un servizio remoto
async function recuperaPagina(numeroPagina) {
  await new Promise((risolvi) => setTimeout(risolvi, 300));

  const pagina = pagine[numeroPagina];

  if (!pagina) {
    throw new Error("Pagina non trovata");
  }

  return pagina;
}

// Variante con for:
// utile quando conosciamo il numero totale di pagine
async function caricaConFor() {
  const risultati = [];

  for (let indice = 0; indice < pagine.length; indice++) {
    const risposta = await recuperaPagina(indice);

    for (const prodotto of risposta.dati) {
      risultati.push(prodotto);
    }
  }

  return risultati;
}

// Variante con while:
// utile quando la risposta indica dinamicamente la pagina successiva
async function caricaConWhile() {
  const risultati = [];
  let numeroPagina = 0;
  let paginaSuccessiva = numeroPagina;

  while (paginaSuccessiva !== null) {
    const risposta = await recuperaPagina(paginaSuccessiva);

    for (const prodotto of risposta.dati) {
      risultati.push(prodotto);
    }

    paginaSuccessiva = risposta.paginaSuccessiva;
  }

  return risultati;
}

// Variante con do...while:
// la prima richiesta viene sempre eseguita
async function caricaConDoWhile() {
  const risultati = [];
  let numeroPagina = 0;
  let paginaSuccessiva;

  do {
    const risposta = await recuperaPagina(numeroPagina);

    for (const prodotto of risposta.dati) {
      risultati.push(prodotto);
    }

    paginaSuccessiva = risposta.paginaSuccessiva;

    if (paginaSuccessiva !== null) {
      numeroPagina = paginaSuccessiva;
    }
  } while (paginaSuccessiva !== null);

  return risultati;
}

// Funzione di stampa e analisi dei risultati
function mostraRisultati(prodotti, titolo) {
  const totale = prodotti.reduce(
    (somma, prodotto) => somma + prodotto.prezzo,
    0
  );

  console.log(`n${titolo}`);
  console.log(`Prodotti caricati: ${prodotti.length}`);
  console.log(`Valore complessivo: ${totale} euro`);

  for (const prodotto of prodotti) {
    console.log(`- ${prodotto.nome}: ${prodotto.prezzo} euro`);
  }
}

// Esecuzione del programma
async function avvia() {
  try {
    const conFor = await caricaConFor();
    const conWhile = await caricaConWhile();
    const conDoWhile = await caricaConDoWhile();

    mostraRisultati(conFor, "Risultati con for");
    mostraRisultati(conWhile, "Risultati con while");
    mostraRisultati(conDoWhile, "Risultati con do...while");
  } catch (errore) {
    console.error("Errore durante il caricamento:", errore.message);
  }
}

avvia();

Spiegazione

Il ciclo for

Nel metodo caricaConFor() utilizziamo for per attraversare tutte le posizioni dell’array pagine. La struttura è composta da inizializzazione, condizione e incremento:

for (let indice = 0; indice < pagine.length; indice++) {
  // Istruzioni eseguite per ogni pagina
}

Questo approccio è adatto quando il programma conosce già il numero delle pagine. È semplice e prevedibile, ma dipende dalla disponibilità di pagine.length. Con un’API reale, il numero totale potrebbe non essere noto in anticipo.

Il ciclo while

Il metodo caricaConWhile() continua finché paginaSuccessiva non diventa null. Il controllo viene eseguito prima del blocco:

while (condizione) {
  // Istruzioni ripetute
}

Questo modello è particolarmente utile con le API che restituiscono un token, un URL o un numero di pagina successivo. È importante aggiornare la variabile di controllo all’interno del ciclo; altrimenti si rischia di creare un ciclo infinito.

Il ciclo do...while

Con do...while il blocco viene eseguito almeno una volta, perché la condizione viene verificata alla fine:

do {
  // Prima esecuzione garantita
} while (condizione);

Questa caratteristica è utile quando sappiamo che almeno una pagina deve essere richiesta. Anche se l’API restituisse subito null come pagina successiva, la prima risposta verrebbe comunque elaborata.

Il ciclo annidato

Nel programma è presente anche un ciclo for...of dentro ciascun metodo. Il ciclo esterno attraversa le pagine, mentre quello interno attraversa i prodotti contenuti nella pagina corrente. Questa tecnica si chiama ciclo annidato e consente di lavorare con dati organizzati su più livelli.

Best practice

  • Preferisci una condizione di uscita chiara: assegna sempre il valore della pagina successiva prima di ripetere il ciclo.
  • Evita cicli infiniti: verifica che almeno una variabile usata nella condizione venga modificata a ogni iterazione.
  • Gestisci gli errori: le richieste di rete possono fallire, quindi usa try...catch attorno alle operazioni asincrone.
  • Usa await con attenzione: in questo esempio le pagine vengono caricate una alla volta, rispettando l’ordine. È una scelta corretta quando la pagina successiva dipende dalla risposta precedente.
  • Limita il numero di dati: se un’API può restituire migliaia di pagine, imposta eventualmente un limite massimo per evitare consumi eccessivi.
  • Separa le responsabilità: una funzione dovrebbe occuparsi del caricamento, un’altra dell’elaborazione e un’altra ancora della visualizzazione.
  • Usa nomi descrittivi: variabili come paginaSuccessiva e risultati rendono il codice più leggibile.

Riepilogo

I cicli for, while e do...while risolvono problemi simili, ma sono adatti a situazioni differenti. for è indicato quando il numero di iterazioni è noto. while è preferibile quando la ripetizione dipende da un valore aggiornato dinamicamente. do...while è utile quando almeno un’esecuzione deve avvenire prima del controllo.

La paginazione delle API è un caso reale in cui queste differenze diventano evidenti. Imparare a scegliere il ciclo corretto permette di creare codice più sicuro, leggibile e facile da manutenere.

Approfondisci con risorse ufficiali

SHARE