JavaScript per Sviluppatori Python (Parte 2)

Pubblicato da Michele Saba

Utilizzare JavaScript con la console del browser

Allo stesso modo in cui con Python utilizziamo la funzione print(), con JavaScript utilizziamo console.log() per mostare i valori in output in un terminale che chiamiamo console.

In qualsiasi browser possiamo aprire il pannello DevTools (Strumenti per Sviluppatori), che ha tutta una serie di funzionalità tra cui lo strumento Inspector, utilizzato per esaminare il codice HTML e CSS, e la console con cui possiamo eseguire il codice JavaScript. Nella maggior parte dei browser (Chrome, Firefox, Edge, Brave, Opera, ecc.) si apre premendo F12 e selezionando la scheda "Console", (su Safari si apre con “Command+Option+C”) oppure cliccando con il tasto destro del mouse su una pagina aperta e selezionando la voce “Ispeziona”, “Esamina”, “Analizza” o una voce del menù equivalente a seconda del browser.

Apriamo il nostro editor di codice (io sto utilizzando Visual Studio Code) e la pagina del browser con la console aperta. Per aprire la nostra pagina HTML nel broswser possiamo utilizzare un server oppure direttamente copiare il percorso del file nella barra degli indirizzi.

Screenshot schermo con editor e pagina del browser aperti

Proviamo a scrivere ed eseguire codice JS tramite la console, ad esempio definiamo una variabile x e inizializziamola a 10:

Esempio di utilizzo console browser

La console è particolarmente comoda in fase di debugging del codice: molti degli errori delle funzioni o di comunicazione con un server possono essere visualizzati nel log nella console, il che la rende uno strumento davvero davvero importante in fase di sviluppo. Vedremo anche come sia possibile manipolare i valori tramite essa e notare i corrispettivi i cambiamenti avvenire nelle pagine web che stiamo utilizzando.

Per il momento inviamo clear() per pulire la schermata:

> clear()


Inserire codice JavaScript in un file HTML

Creiamo un file HTML chiamato hello-world.html: il modo più immediato di introdurre codice JavaScript nella nostra pagina consiste nel scriverlo all’interno del tag <script> direttamente nell’<head>:

<!DOCTYPE html>
<html lang="it" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>Hello World</title>
  <script type="text/javascript">
		// codice JS
  </script>
</head>

<body>

</body>

</html>

Perciò all’interno del tag <script> definiamo una funzione utilizzando la parola chiave function, chiamiamola helloWorld() e utilizziamo due parentesi graffe per andare a definire il blocco di codice. Inseriamo la funzione alert(), passiamole una stringa per mostrare un pop up nella pagina e richiamiamola:

function helloWorld() {
  alert('Ciao a tutti!');
}
helloWorld();

Se effettuiamo il refresh della pagina comparirà il pop-up:

Pop-up js ciao a tutti

Possiamo chiedere all'utente che sta visitando la nostra pagina di inserire dei dati tramite la funzione prompt(). Utilizziamola per chiedere un nome definendo una variabile e assegnandola a prompt() a cui passiamo un messaggio da visualizzare nel pop up. Mostriamo il nome concatenando delle stringhe e passandole ad alert():

function helloWorld() {
  let name = prompt("Come ti chiami?");
  alert('Ciao ' + name + "!");
}
helloWorld();

Effettuiamo il refresh della pagina e ci verrà chiesto il nome:

Pop-up js come ti chiami

Se lo inseriamo ci verrà mostrato nel pop-up:

pop up ciao con nome inserito

Come abbiamo visto nella prima parte della guida, possiamo utilizzare anche i Template Literal al posto di usare + per effettuare delle concatenazioni tramite i backtick e il simbolo del dollaro seguito da parentesi graffe:

function helloWorld() {
  let name = prompt("Come ti chiami?");
  alert(`Ciao ${name}`);
}
helloWorld();

A seconda del layout della tastiera che state utilizzando, per digitare l’accento grave dovrete utilizzare una combinazione di tasti, che generalmente per la maggior parte delle tastiere è ALT+0096 (i numeri devono essere digitati sul pad numerico).


Eseguire una funzione alla pressione di un tasto

Vediamo come sia possibile eseguire una funzione alla pressione di un tasto all'interno della nostra pagina HTML. Per prima cosa commentiamo la riga con la chiamata alla funzione utilizzando il doppio slash //:

// helloWorld();

Inseriamo all’interno dei tag <body> un titolo <h1> e creiamo un tasto a cui colleghiamo la nostra funzione tramite l’attributo onclick:

<body>
  <h1>Ciao! Benvenuti"</h1>
  <button onclick="hello_world()">Premimi!</button>
</body>

Facciamo il refresh della pagina e se premiamo il tasto apparirà il popup:

Screenshot pop up collegato al tasto js


Che cos’è il DOM?

Come abbiamo detto nella prima parte della guida, JavaScript viene spesso utilizzato per migliorare l'esperienza degli utenti aggiungendo degli effetti grafici o interattivi come eventi alla pressione di un tasto oppure l'inserimento di codice HTML in maniera dinamica nelle pagine web come avviene ad esempio in framework come Vue.js. Ma come fa JavaScript a sapere che deve eseguire il codice associato ad una funzione quando l’utente clicca su un tasto?

Questo è possibile grazie al DOM (Document Object Model), a cui possiamo pensare come a un'interfaccia tra il codice JavaScript, HTML e CSS: quando una pagina viene caricata il browser, il DOM (come dice il nome stesso, che signidica “Modello a oggetti del documento”) crea una rappresentazione di tutti gli elementi presenti considerandoli come oggetti.

Gli elementi del DOM sono spesso tra di loro imparentati e collegati tra loro, quindi, come possiamo vedere nello schema, presenta una struttura ad albero in cui tutti i nodi fanno riferimento a quello principale Document, che rappresenta la pagina in sé:

Schema ad albero DOM

Quindi il DOM ci permette di compiere svariate azioni come cambiare, aggiungere o eliminare elementi delle pagine HTML, reagire ad eventi come alla pressione di un tasto o del mouse, o cambiare lo stile e quindi l'aspetto dei nostri contenuti.

Dal momento che il nodo Document rappresenta la pagina caricata nella finestra del browser, possiamo effettuare tutta una serie di selezioni o di modifiche sulla pagina stessa selezionando i vari nodi “figli” e modificando il codice HTML, ad esempio se andiamo sulla console possiamo cambiare il titolo della pagina in questo modo:

> document.title = "un altro titolo"

Ma dopo il refresh della pagina il titolo tornerà ad essere “Hello World” perché la console non è in grado di modificare la versione permanente della pagina! È possibile farlo solo modificando il codice sorgente caricato sul server.


Modificare un elemento della pagina con JavaScript

Tramite tag

Possiamo richiamare attraverso l’oggetto document dei metodi per selezionare tutti gli altri elementi del DOM. Ci sono tanti diversi identificatori che possiamo utilizzare per questo scopo; noi per ora utilizzeremo il metodo querySelector().

Chiamiamo il metodo querySelector() su document e passiamogli il tag <h1> come argomento. Utilizziamo poi la proprietà innerHTML per impostare come contenuto del titolo la stringa “Arrivederci!”:

function cambiaMessaggio() {
  document.querySelector('h1').innerHTML = "Arrivederci!";
}

Ora alla pressione del tasto click il titolo cambierà da “Ciao! Benvenuti!” a “Arrivederci!”.

Il metodo querySelector() seleziona il primo elemento corrispondente alla selezione che abbiamo passato: se dovessimo inserire un altro <h1> verrebbe modificato solo il primo.

Tramite id

Facciamo un altro esempio con querySelector() dove invece di utilizzare un elemento html utilizziamo direttamente un id. Inizializziamo una variabile contatore a 0 e modifichiamo la nostra funzione rinominandola count() e facendo in modo che mostri il valore della variabile nell’elemento che ha come id “contatore”. Come di consueto in HTML e CSS, per riferirci ad un id utilizziamo il cancelletto #. Tramite l’operatore di incremento ++ facciamo in modo che la variabile contatore venga incrementata di 1 ogni volta che la funzione viene chiamata.

let contatore = 0;

function count() {
  contatore++;
  document.querySelector("#contatore").innerHTML = contatore;
}

Assegniamo al nostro titolo <h1> l’id “contatore” e al tasto la funzione count() tramite l’attributo onclick:

<body>
  <h1 id="contatore">0</h1>
  <button onclick="count()">click</button>
</body>

Adesso il titolo mostrerà il numero di volte che premiamo il pulsante “click”. Apriamo la console e modifichiamo il valore della variabile contatore:

> contatore
< 7
> contatore = 20
< 20

Se adesso premiamo il pulsante, la pagina ci mostrerà come <h1> il numero 21.


Implementare una struttura di controllo con if

Vediamo un esempio un po’ più complesso aggiungendo una struttura di controllo. Dichiariamo un'altra variabile con let chiamata array_numero e assegniamola a un array di numeri (che in Python chiameremmo una lista). Con l'istruzione if facciamo in modo che venga mostrato un popup con la funzione alert() se il valore associato al nostro contatore in un determinato momento è presente all'interno dell’array.

let contatore = 0;
let array_numero = [5, 7, 11, 13];

function count() {
  contatore++;
  document.querySelector("#contatore").innerHTML = contatore;
  if (array_numero.includes(contatore)) {
    alert(`Contatore a ${contatore}: presente in array!`);
  }
}

Aggiungiamo anche la clausola else per mostrare nel log il valore di contatore qualora non fosse presente nell’array:

function count() {
  // ...
  if (array_numero.includes(contatore)) {
    alert(`Contatore a ${contatore}: presente in array!`);
  } else {
    console.log(contatore);
  }
}


Eseguire una funzione appena la pagina viene caricata

Nel nostro codice stiamo chiamando la funzione count() direttamente con l'evento onclick: all'interno di contesti semplici questa pratica va benissimo, ma in progetti più complessi potrebbe complicarci la modifica del codice perché, ad esempio, se dovessimo decidere di cambiare il nome di una funzione dovremmo andare a modificare anche il codice di conseguenza dove viene chiamata.

In alternativa possiamo quindi mettere la nostra pagina in ascolto per un evento che corrisponda al caricamento del DOM e quindi eseguire una funzione appena la pagina è stata generata. Per fare ciò chiamiamo il metodo addEventListener() su document per registrare un gestore di eventi che verrà chiamato quando l'intero documento HTML è stato caricato e analizzato dal browser tramite una funzione anonima. Passiamo quindi alla funzione la chiamata di document al metodo querySelector(), a cui assegniamo il tasto in modo che la funzione venga chiamata quando viene cliccato.

document.addEventListener("DOMContentLoaded", function () {
  document.querySelector("button").onclick = count;
})

Torniamo nel browser e facciamo refresh: vedremo che tutto funziona anche in questo caso.


Separare il codice JavaScript dall’HTML

Per migliorare l’organizzazione del codice possiamo separare il codice JavaScript dalla pagina HTML e collegarlo al file tramite l’elemento script.

Copiamo il nostro codice in un nuovo file, io l’ho chiamato "06-main.js" per tenere traccia degli esempi della guida all’interno del repository. Se il file .js che abbiamo creato si trova nella stessa cartella del nostro .html come in questo caso, ci basta inserire questo codice all’interno dell’head:

<script src="06-main.js"></script>

Esattamente come è buona pratica fare con il CSS, separare il codice JavaScript dall’HTML è senza dubbio il metodo migliore per organizzare il nostro progetto quando lavoriamo su un sito o su una web app: in questo modo è più facile mantenere il codice più organizzato e leggibile e possiamo renderlo utilizzabile in più pagine invece che ripeterlo in ogni file.


Manipolare i dati di un form HTML con JavaScript

Una delle funzionalità tra le più utilizzate di JavaScript è la gestione dei form: creiamo un nuovo file HTML con un campo testuale input per fare in modo che l’utente possa inserire il suo nome per mostrargli un pop up personalizzato. Assegniamo un id ai tag form e input e a quest’ultimo assegniamo un placeholder con una stringa testuale e l’attributo type per indicare il campo di entry e il pulsante per inviare la risposta.

<form id="nameForm">
  <input id="nameInput" type="text" placeholder="Inserisci il tuo nome!">
  <input type="submit">
</form>

Scriviamo quindi il codice JavaScript per gestire i dati del form: utilizziamo il metodo addEventListener per registrare il gestore di eventi e inseriamo il metodo querySelector passandogli l’id del campo <input> come abbiamo fatto finora, facendo in modo che la funzione venga chiamata quando viene inviato il form con onsubmit e mostri il nome con la funzione alert:

document.addEventListener("DOMContentLoaded", function () {
  document.querySelector("#nameForm").onsubmit = function () {
    const name = document.querySelector("#nameInput").value;
    alert(`Il tuo nome è ${name}`)
  };
})

Perciò, quando il DOM finisce di caricare la funzione si metterà in ascolto. Alla pressione di submit per l'invio del form verrà chiamata un'altra funzione che mostrerà il valore associato all’input testuale con un pop up.


Impedire il ricaricamento della pagina con preventDefault()

Quando in una pagina web viene scatenato un evento come l'invio di un form, viene eseguito il comportamento di default associato ad esso. Il comportamento di default associato all’evento "submit" consiste nel ricaricare la pagina. Tramite la funzione callback il nome inserito viene visualizzato in un popup di alert e quando premiamo il tasto “Ok”, la pagina viene ricaricata come di default. Nella maggior parte dei casi è preferibile fare in modo che non venga ricaricata l’intera pagina ma che le comunicazioni tra server e client siano asincrone.

Le richieste asincrone consentono di utilizzare meglio le risorse del server minimizzando il numero di manipolazioni del DOM e rendono l'applicazione più efficiente e reattiva: è possibile anche effettuare molte richieste contemporaneamente, senza dover attendere il completamento di una prima di iniziare la successiva. Questo tipo di esecuzione risulta particolarmente utile quando si utilizza un framework come Vue.js o React.

JavaScript ci dà la possibilità di prevenire l'evento di default del form utilizzando il metodo preventDefault(). Passiamo la variabile e (che rappresenterà l’evento) come argomento della nostra funzione e chiamiamo il metodo sull’oggetto e per impedire alla pagina di essere ricaricata quando viene inviato il form. Recuperiamo il valore inserito nell'elemento di input con id "nameInput" utilizzando il metodo "value" dell'oggetto dell'elemento, mostriamo il messaggio pop-up con il nome inserito dall'utente e ripuliamo l’input impostando il valore dell'elemento alla stringa vuota "".

document.addEventListener("DOMContentLoaded", function () {
  document.querySelector("#nameForm").onsubmit = function (e) {

    // preveniamo l'evento di default con conseguente reload della pagina
    e.preventDefault();

    // recuperiamo il nome associato ad input
    const name = document.querySelector("#nameInput").value;

    // ripuliamo l'input
    alert(`Il tuo nome è ${name}`);

    document.querySelector("#nameInput").value = "";

  };
})

In alternativa, possiamo inserire "return false" per bloccare il submit del form e impedire il caricamento della pagina, ma nella maggior parte dei casi viene utilizzato più comunemente e.preventDefault().

document.addEventListener("DOMContentLoaded", function () {
  document.querySelector("#nameForm").onsubmit = function (e) {

    // e.preventDefault();

    const name = document.querySelector("#nameInput").value;
    alert(`Il tuo nome è ${name}`);
    document.querySelector("#nameInput").value = "";

    // avremmo potuto usare anche questo per bloccare il submit
    return false;

  };
})

Per rendere il nostro codice più leggibile possiamo sostituire la sintassi di creazione delle funzioni con quella delle Arrow Function:

document.addEventListener("DOMContentLoaded", () => {
  document.querySelector("#nameForm").onsubmit = e => {

    // ...

  };
})

Vi è comunque da tenere in considerazione una differenza importante tra le Arrow Gunction e le funzioni “standard”: la vedremo nel dettaglio tra poco.


Cambiare il colore di un singolo elemento della pagina con querySelector()

Creiamo una nuova pagina HTML che mostri un quadrato con un bordo nero e al di sotto di esso tre tasti che permettono di cambiarne il colore. Aggiungiamo un <div> per il box e e tre pulsanti <button> con un id che corrisponde al colore associato:

<!DOCTYPE html>
<html lang="it" dir="ltr">

<head>
  <style></style>
  <script></script>
  <title>Box Colorato</title>
</head>

<body>
  <div id="box">
  </div>
  <br>
  <button id="red">Rosso</button>
  <button id="orange">Arancione</button>
  <button id="green">Verde</button>
</body>

</html>

Nel CSS impostiamo le dimensioni del nostro box e assegniamogli un bordo nero:

#box {
	width: 200px;
	height: 200px;
	border: 3px solid black;
}

Tramite JavaScript aggiungiamo un evento "DOMContentLoaded" al nostro document. Quando il documento verrà caricato, il codice eseguirà le seguenti tre funzioni di callback alla pressione al tasto che indica il colore corrispondente per modificare lo sfondo dell’elemento di id “box”:

document.addEventListener('DOMContentLoaded', function () {

  // Cambia il colore di sfondo del box a "red"
  document.querySelector('#red').onclick = function () {
    document.querySelector('#box').style.background = 'red';
  };

  // Cambia il colore di sfondo del box a "orange"
  document.querySelector('#orange').onclick = function () {
    document.querySelector('#box').style.background = 'orange';
  };

  // Cambia il colore di sfondo del box a "green"
  document.querySelector('#green').onclick = function () {
    document.querySelector('#box').style.background = 'green';
  };
});

Se carichiamo la pagina, vedremo il box e potremo cambiarne il colore:

Quadrato con tasti per cambio colore


Cambiare il colore degli elementi di una classe con querySelectorAll()

Il sistema che stiamo utilizzando per fare in modo che venga selezionato il colore corrispondente al tasto premuto non è efficiente perché determina la ripetizione della stessa riga di codice più volte. Al posto di utilizzare il metodo querySelector(), che ci permette di selezionare un unico elemento del DOM, possiamo modificare la nostra funzione in modo da implementare querySelectorAll() in modo da selezionare tutti gli elementi di una classe chiamata color-change.

Tramite il metodo forEach() iteriamo tra le funzioni callback corrispondenti ai tasti presenti e alla pressione di ciascuno di essi il colore verrà modificato in maniera dinamica in base al data attribute (che assegneremo ai tasti nel codice HTML):

document.addEventListener('DOMContentLoaded', function () {

  // Cambia il colore di sfondo del box
  document.querySelectorAll('.color-change').forEach(button => {
    button.onclick = () => {
      document.querySelector("#box").style.background = button.dataset.color;
    }
  })

});

Modifichiamo il nostro file HTML sostituendo gli id alla classe color-change e assegnando loro il data attribute data-color che verrà utilizzato dalla funzione di callback.

<body>
  <div id="box">
  </div>
  <br>
  <button class="color-change" data-color="red">Rosso</button>
  <button class="color-change" data-color="orange">Arancione</button>
  <button class="color-change" data-color="green">Verde</button>
</body>

Se facciamo refresh vedremo che il funzionamento del nostro box è identico a prima, ma il nostro codice è molto più ordinato.


Differenze sul contesto this tra funzioni Arrow e Standard

Per la scrittura delle nostre funzioni nel codice JavaScript abbiamo utilizzato la notazione delle Arrow Function per semplificare il nostro codice e renderlo più leggibile, ma, come abbiamo accennato, ci sono situazioni in cui le funzioni arrow non sono adatte e possono comportarsi in modo molto diverso dalle funzioni “standard”.

Creiamo un nuovo file HTML e implementiamo un menù select con svariate opzioni associate a nomi di colori predefiniti accessibili tramite CSS:

<body>
  <div id="box">
  </div>
  <br>
  <select id="colorChange">
    <option selected disabled>Seleziona un Colore</option>
    <option value="red">Rosso</option>
    <option value="orange">Arancione</option>
    <option value="green">Verde</option>
    <option value="blue">Blu</option>
    <option value="purple">Viola</option>
    <option value="grey">Grigio</option>
    <option value="black">Nero</option>
  </select>
  <hr>
  <button onclick="this.style.display='none'">Clicca per Rimuovermi</button>
</body>

Nel nostro codice JS facciamo in modo che al caricamento del DOM venga eseguita una funzione anonima che selezioni l’elemento HTML con l'id "colorChange" e gli aggiunga il gestore di eventi "onchange" ogni volta che il valore del campo di input viene modificato.

La funzione selezionerà l'elemento HTML con l'id "box" e cambierà il colore di sfondo dell'elemento con il valore del campo di input utilizzando la proprietà "background" dello stile CSS.

document.addEventListener('DOMContentLoaded', function () {

  document.querySelector('#colorChange').onchange = function () {
    document.querySelector('#box').style.background = this.value;
  };

});

Abbiamo dichiarato la funzione anonima con function e poi abbiamo utilizzato una parola chiave molto importante in JavaScript: this. Attenzione, perché questo è possibile solo con le funzioni standard!

Nelle funzioni standard, il valore di this dipende dal contesto di esecuzione in cui vengono chiamate, mentre le arrow function non hanno un valore this legato all’oggetto corrente, ma lo ereditano dalla funzione “genitore” in cui sono state dichiarate. Nel nostro caso, la funzione padre è l'evento DOMContentLoaded, quindi this si riferisce all'oggetto window, ovvero la finestra del browser che contiene document.

Indipendentemente dal modo in cui viene chiamata l'Arrow function, il valore di this sarà lo stesso del contesto in cui è stata definita, quindi il codice seguente non ci permetterà di cambiare il colore del box:

// Questo codice non funzionerà

document.addEventListener('DOMContentLoaded', function () {

  document.querySelector('#colorChange').onchange = () => {
    document.querySelector('#box').style.background = this.value;
  };

});

Possiamo utilizzare la parola chiave this per rimuovere un pulsante dopo averlo premuto direttamente dal file HTML assegnandogli un selettore CSS:

<body>
  <!-- ... -->
  <hr>

  <button onclick="this.style.display='none'">Clicca per Rimuovermi</button>
</body>


Fare richieste asincrone a un’API tramite la funzione fetch()

Vediamo come utilizzare la funzione fetch() di JavaScript per effettuare delle richieste asincrone verso le API (Application Programming Interface), sistemi che ci permettono di comunicare con i servizi offerti da una web app o da un sito.

Il nostro codice JS comunicherà con gli endpoint dell’API di Frankfurter, un sito che fornisce dati riguardanti differenti cambi tra valute: possiamo trovare la guida su come utilizzare la API direttamente nella documentazione del sito. Dalla documentazione possiamo vedere che le chiamate che effettueremo, se andranno a buon fine, ci restituiranno un .json.

Creiamo un nuovo file .html e iniziamo a implementare con JavaScript una funzione chiamata getCurrencyRate() che per il momento non accetta parametri ma a cui passeremo il nome di una valuta. Associamo l’endpoint dell’API ad una nuova variabile url e passiamolo a fetch(): in italiano significa “recuperare” o “andare a prendere”.

function getCurrencyRate() {
  let url = "https://api.frankfurter.app/latest";
  fetch(url)

fetch() è una funzione di JavaScript che permette di fare richieste HTTP asincrone a un server e ricevere delle risposte. L’URL è l’unico parametro necessario per poter recuperare la risposta con fetch(), ma è possibile anche personalizzare la richiesta passando come argomento a fetch() anche un oggetto config che specifichi opzioni aggiuntive come il metodo HTTP utilizzato di default (GET, POST, PUT, ecc.) e il contenuto della richiesta rappresentandolo come oggetto JSON e convertendolo in stringa con il metodo stringify().

function getCurrencyRate() {
  let url = "https://api.frankfurter.app/latest";

    const config = {
    method: "POST", // "POST", "PUT"
    body: JSON.stringify(data)
    }

  fetch(url, config)

Per ora noi non specificheremo opzioni aggiuntive e utilizzeremo solo GET.


Cosa sono le Promise?

La funzione fetch() in JavaScript restituisce una promise (”promessa”) che rappresenta l’eventuale successo (o fallimento) di un’operazione asincrona e può trovarsi in tre stati differenti:

  • Pending: lo stato iniziale della promise, che indica che la promessa è in attesa di essere risolta o rigettata.
  • Fulfilled: tutto è andato a buon fine e la promise è stata risolta con successo.
  • Rejected: qualcosa non è andato per il verso giusto e la promessa è stata rigettata.

Quando la risposta viene completata con successo, la promessa viene risolta con un oggetto Response contenente informazioni sulla risposta HTTP, come l'intestazione, il codice di stato e il corpo della risposta. In tal caso il successo della promise si gestisce utilizzando il metodo then(): utilizziamolo per mostrare in log lo status dell’oggetto Response. Vedremo tra breve anche come gestire il fallimento della promise utilizzando il metodo catch().

function getCurrencyRate() {
  let url = "https://api.frankfurter.app/latest";

	fetch(url)
    .then(function (response) {
	    console.log("Status: ", response.status);
	  })
}
getCurrencyRate();

Nella console dovremmo vedere il codice di stato 200.

Convertire una Valuta

Adesso faremo in modo che il nostro codice recuperi il tasso di cambio più recente di una valuta a nostra scelta rispetto all'Euro utilizzando l'API. Modifichiamo la dichiarazione della funzione getCurrencyData() in modo che accetti come argomento la variabile currency, che conterrà il nome della valuta che vogliamo comparare all’Euro.

Modifichiamo la stringa contenente l’endpoint per inserire il parametro from, che ci servirà per confrontare le valute. Con la funzione response.json() convertiamo il corpo della risposta in un oggetto JavaScript, che passiamo come parametro alla funzione di callback che stampa il risultato della richiesta nella console concatenando il messaggio "Fetch Result: " con l'oggetto che rappresenta il tasso di cambio richiesto.

function getCurrencyRate(currency) {
  console.log(currency);

  let url = "https://api.frankfurter.app/latest?from=" + currency;

  fetch(url).then(function (response) {
    console.log("Status: ", response.status);

    response.json().then(function (data) {
      console.log("Fetch Result: ", data);
    })
  })
}
getCurrencyRate("USD");

Se riavviamo la pagina otteniamo lo status 200 e le informazioni sulla data e il valore della valuta richiesta rispetto all’Euro.


Utilizzare un form per chiedere un input all’utente

Creiamo una pagina HTML in cui utilizzeremo JavaScript per prendere dei dati dall API di Frankfurter come abbiamo appena fatto, ma chiedendo all’utente la valuta da utilizzare come base di conversione tramite un form HTML. Tramite JS reperiremo l’input, effettueremo la richiesta e infine mostreremo i risultati nella pagina.

Per prima cosa creiamo un file HTML con un form e un <h2> che utilizzeremo per mostrare la conversione:

<!DOCTYPE html>
<html lang="it" dir="ltr">

<head>
  <meta charset="utf-8">
  <script src="14-main.js"></script>
</head>

<body>
  <p>Inserisci una valuta per ottenere i tassi di cambio con l'Euro</p>
  <form id="form">
    <input id="currency" type="text" placeholder="Valuta">
    <input type="submit" value="Converti">
  </form>
  <br>
  <h2 id="exchangeResults"></h2>
</body>

</html>

Scriviamo quindi il codice JavaScript cominciando con la scrittura della funzione getJSON(), che deve prendere come parametro una risposta HTTP e restituire a sua volta una promise per i dati JSON (estratti con il metodo json()) contenuti nella risposta.

function getJSON(response) {
  let data = response.json();
  return data
}

Implementiamo la funzione getCurrencyRate(), che ottiene i tassi di cambio di una valuta specifica prendendo come parametro currency come abbiamo fatto nell’altra pagina che abbiamo creato. Gestiamo la promise con fetch e facciamo in modo che venga chiamata una funzione getJSON() sulla risposta quando i dati JSON restituiti dall’API sono disponibili.

Se si verifica un errore durante la chiamata o l'elaborazione dei dati JSON e la promise fallisce, tramite il metodo catch() viene eseguita una funzione di callback che mostra l'errore sulla console.

function getCurrencyRate(currency) {

  let url = "https://api.frankfurter.app/latest?from=" + currency;

  fetch(url)
    .then(getJSON)
    .then(data => {
      console.log("Data: ", data);
    })
    .catch( err => {
      console.log("Error: ", err);
    })
}

Per scrivere la nostra funzione abbiamo utilizzato le chaining promises (”promesse concatenate”), una tecnica in JavaScript per concatenare più chiamate asincrone (che restituiscono promesse) in una sequenza ordinata di operazioni.

Reperire i dati dal form

Ora che abbiamo completato la parte di codice che ci permette di reperire i dati tramite l’endpoint dell’API, dobbiamo fare in modo che lo script prenda dal form HTML il valore di input inserito dall’utente e lo assegni a currency. Aggiungiamo un event listener al documento che si attivi quando il contenuto HTML è stato completamente caricato. Quando l'evento viene attivato, viene eseguita una funzione che viene assegnata all'evento onsubmit del form con id "form".

Preveniamo il il comportamento di default del form, ovvero il ricaricamento della pagina, tramite preventDefault() e recuperiamo il valore inserito dall'utente nel campo di input con id “currency” assegnandolo alla costante currency. Questo valore rappresenta la valuta che l'utente vuole utilizzare per la conversione.

Aggiungiamo quindi una chiamata a getCurrencyRate(), passando currency come argomento la valuta inserita dall'utente e ripuliamo il campo di input testuale impostandolo su una stringa vuota.

document.addEventListener("DOMContentLoaded", () => {
  document.querySelector("#form").onsubmit = event => {

    // preveniamo il reload della pagina
    event.preventDefault();
    
    // prendiamo la valuta che vogliamo usare per la conversione
    const currency = document.querySelector("#currency").value;

    // richiamiamo la funzione passandole la valuta inserita dall'utente
    getCurrencyRate(currency);

    // "ripuliamo" l'input testuale
    document.querySelector("#currency").value = "";

  }
})

Per il momento i dati vengono mostrati solo in console. Per fare in modo di mostrarli nella pagina, modifichiamo la nostra funzione getCurrencyRate() commentando i console.log() e utilizzando l’id “exchangeResults” del titolo H2 che abbiamo inserito nel nostro file HTML per mostrare il confronto tra valute sulla pagina tramite querySelector() (oppure per mostrare l’eventuale errore):

function getCurrencyRate(currency) {

  let url = "https://api.frankfurter.app/latest?from=" + currency;

  fetch(url)
    .then(getJSON)
    .then(data => {
      // console.log("Data: ", data);
      let rate = Object.values(data.rates)[0];
      document.querySelector("#exchangeResults").innerHTML = `1.00 Euro corrisponde a ${ rate } ${ currency }`;
    })
    .catch( err => {
      // console.log("Error: ", err);
      document.querySelector("#exchangeResults").innerHTML = `Errore ${ err }`;
    })
}

Se ricarichiamo la pagina potremo scegliere con quale valuta effettuare la conversione:

Conversione Valuta Programma Concluso

Abbiamo concluso la nostra pagina web!


Complimenti per essere arrivati alla fine di questa guida. Spero che sia stata di vostro completo gradimento e che abbiate appreso tutto ciò che era mia intenzione comunicarvi.

Dovreste ora disporre di tutti gli strumenti necessari a permettervi di sviluppare semplici script JavaScript lato client e dovreste inoltre essere in grado di poter iniziare ad apprendere framework avanzati come React e Vue JS. A tal proposito vi ricordo che in Academy abbiamo un corso pensato per insegnarvi proprio a fare ciò chiamato Guida per Sviluppatori a Django REST Framework e Vue JS. Se vi siete già iscritti potete trovarlo in Academy, diversamente se avete gradito questa guida, scoprite di più e iscrivetevi!


Vuoi imparare Python come un/a professionista? Dai uno sguardo ai nostri