Esercizio 11 API
This commit is contained in:
93
javascript/JS_Esercizi 11 - API/tutorial/index.html
Normal file
93
javascript/JS_Esercizi 11 - API/tutorial/index.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<title>API e Asincronia</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="controls">
|
||||
<h1>Tutorial: API e Asincronia</h1>
|
||||
<button id="btn-esegui">▶️ Esegui Codice</button>
|
||||
<button id="btn-reset">🧹 Pulisci Console</button>
|
||||
<a href="../index.html" style="position: absolute; top: 20px; left: 20px; text-decoration: none; color: #555; font-weight: bold;">← Dashboard</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function mostraOutput(stepNumero, messaggio) {
|
||||
const elemento = document.getElementById(`output-${stepNumero}`);
|
||||
if (elemento) {
|
||||
messaggio = messaggio || "❌";
|
||||
let isObject = (typeof messaggio === 'object' && messaggio !== null);
|
||||
elemento.textContent = isObject ? JSON.stringify(messaggio, null, 2) : String(messaggio);
|
||||
elemento.classList.remove("loading");
|
||||
|
||||
elemento.style.transition = "";
|
||||
elemento.style.backgroundColor = "#666";
|
||||
setTimeout(() => {
|
||||
elemento.style.transition = "background-color 1s ease";
|
||||
elemento.style.backgroundColor = "#2d3436";
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[
|
||||
{
|
||||
title: "1. Il concetto di Attesa (Simulazione)",
|
||||
description: "Le API sono lente. Simuliamo un ritardo di 2 secondi prima di mostrare il messaggio.",
|
||||
outputLabel: "Output Step 1:"
|
||||
},
|
||||
{
|
||||
title: "2. Prima chiamata Fetch (GET)",
|
||||
description: "Recuperiamo un oggetto JSON reale da un server pubblico.",
|
||||
outputLabel: "Dati ricevuti:"
|
||||
},
|
||||
{
|
||||
title: "3. Estrazione Dati (JSON)",
|
||||
description: "La risposta grezza non basta. Dobbiamo convertirla ed estrarre il titolo.",
|
||||
outputLabel: "Titolo del Post:"
|
||||
},
|
||||
{
|
||||
title: "4. Gestione Errori (Try/Catch)",
|
||||
description: "Proviamo a chiamare un sito che non esiste per vedere se il codice sopravvive.",
|
||||
outputLabel: "Stato operazione:"
|
||||
},
|
||||
{
|
||||
title: "5. Lavorare con le Liste (Array)",
|
||||
description: "Scarichiamo 10 utenti e mostriamo solo i loro nomi.",
|
||||
outputLabel: "Elenco Utenti:"
|
||||
},
|
||||
{
|
||||
title: "6. Invio Dati (POST)",
|
||||
description: "Simuliamo l'invio di un nuovo post al server.",
|
||||
outputLabel: "Risposta Server:"
|
||||
}
|
||||
].forEach((step, i) => {
|
||||
document.write(`
|
||||
<div class="step-card">
|
||||
<div class="step-header">
|
||||
<div class="step-title">${step.title}</div>
|
||||
</div>
|
||||
<div class="step-desc">${step.description}</div>
|
||||
<span class="label">${step.outputLabel}</span>
|
||||
<div id="output-${i + 1}" class="output-box"></div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
</script>
|
||||
<script src="script.js"></script>
|
||||
<script>
|
||||
document.getElementById('btn-reset').addEventListener('click', () => {
|
||||
localStorage.clear();
|
||||
location.reload();
|
||||
});
|
||||
document.getElementById('btn-esegui').addEventListener('click', () => {
|
||||
const el = document.querySelectorAll('[id^="output-"]');
|
||||
el.forEach(box => box.className = "output-box loading");
|
||||
eseguiTutorial();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
115
javascript/JS_Esercizi 11 - API/tutorial/script.js
Normal file
115
javascript/JS_Esercizi 11 - API/tutorial/script.js
Normal file
@@ -0,0 +1,115 @@
|
||||
// TUTORIAL INTERATTIVO: API, Fetch e Async/Await
|
||||
|
||||
// NON TOCCARE
|
||||
// Funzioni di supporto per il tutorial
|
||||
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // Simula server lento
|
||||
|
||||
// Funzione pricipale del tutorial
|
||||
async function eseguiTutorial() {
|
||||
|
||||
/**
|
||||
* ===========================================
|
||||
* === 1. Il Concetto di Attesa ===
|
||||
* JavaScript di solito corre veloce. Con i server, deve aspettare.
|
||||
* La keyword 'await' serve a dire "Fermati qui finché l'operazione non finisce".
|
||||
*/
|
||||
// Questa funzione simula un server che ci mette 2 secondi a rispondere
|
||||
// TODO: Aggiungi 'await' prima di wait(2000) per far funzionare l'attesa.
|
||||
wait(2000);
|
||||
|
||||
mostraOutput(1, "Operazione completata!");
|
||||
|
||||
|
||||
/**
|
||||
* ===========================================
|
||||
* === 2. Fetch Base (GET) ===
|
||||
* Usiamo `fetch(url)` per chiamare un server vero.
|
||||
*/
|
||||
// TODO: crea una costante 'urlBase' con l'indirizzo dettato a lezione
|
||||
// TODO: Esegui una fetch a quell'URL.
|
||||
// Ricorda di mettere 'await' davanti a fetch!
|
||||
const urlBase = "https://sito-finto.com";
|
||||
const rispostaGrezza = null;
|
||||
|
||||
mostraOutput(2, rispostaGrezza ? "Risposta ricevuta (Response Object)" : "");
|
||||
|
||||
|
||||
/**
|
||||
* ===========================================
|
||||
* === 3. Estrarre il JSON ===
|
||||
* La risposta grezza contiene status code, headers, ecc.
|
||||
* A noi servono i dati. Dobbiamo usare il metodo .json().
|
||||
* ANCHE .json() è asincrono e vuole 'await'.
|
||||
*/
|
||||
let nomeUtente = "";
|
||||
|
||||
if (rispostaGrezza) {
|
||||
// TODO: Estrai i dati usando: await rispostaGrezza.json()
|
||||
const dati = {};
|
||||
|
||||
// TODO: Assegna a nomeUtente il valore di dati.nome
|
||||
nomeUtente = "NOME MANCANTE";
|
||||
}
|
||||
|
||||
mostraOutput(3, nomeUtente);
|
||||
|
||||
|
||||
/**
|
||||
* ===========================================
|
||||
* === 4. Gestione Errori (Try / Catch) ===
|
||||
* Se il server è giù o l'URL è sbagliato, fetch esplode.
|
||||
* Usiamo try/catch per gestire il problema.
|
||||
*/
|
||||
try {
|
||||
// TODO: Prova a fare una fetch a un URL sbagliato (es. 'https://sito-finto.com')
|
||||
// Ricorda l'await!
|
||||
|
||||
mostraOutput(4);
|
||||
} catch (errore) {
|
||||
mostraOutput(4, errore.message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ===========================================
|
||||
* === 5. Liste di Dati (Array) ===
|
||||
* Spesso riceviamo un array di oggetti. Dobbiamo ciclarlo.
|
||||
*/
|
||||
// Scarichiamo 5 utenti
|
||||
const responseUtenti = await fetch(`${urlBase}/users?_limit=5`);
|
||||
const listaUtenti = await responseUtenti.json();
|
||||
|
||||
// TODO: Usa .map() o un ciclo for per creare un array contenente SOLO i nomi degli utenti.
|
||||
// Esempio: const nomi = listaUtenti.map(u => u.name);
|
||||
const soloNomi = [];
|
||||
|
||||
mostraOutput(5, soloNomi);
|
||||
|
||||
|
||||
/**
|
||||
* ===========================================
|
||||
* === 6. Inviare Dati (POST) ===
|
||||
* Per inviare dati, fetch accetta un secondo parametro di opzioni.
|
||||
*/
|
||||
// TODO: Completa l'oggetto con i dati mancanti
|
||||
const nuovoUtente = {
|
||||
nome: "",
|
||||
cognome: "",
|
||||
dataNascita: "", // Formato: 'YYYY-MM-DD'
|
||||
comune: "",
|
||||
email: "",
|
||||
attivo: true,
|
||||
avatar: "https://ui-avatars.com/api/?name=Nome+Cognome"
|
||||
};
|
||||
|
||||
// TODO: Completa la fetch.
|
||||
// Aggiungi method: 'POST'
|
||||
// Aggiungi headers: { 'Content-Type': 'application/json' }
|
||||
// Aggiungi body: JSON.stringify(nuovoUtente)
|
||||
const rispInvio = await fetch(`${urlBase}/posts`, {
|
||||
|
||||
});
|
||||
|
||||
const risultatoInvio = await rispInvio.json();
|
||||
mostraOutput(6, risultatoInvio);
|
||||
}
|
||||
116
javascript/JS_Esercizi 11 - API/tutorial/styles.css
Normal file
116
javascript/JS_Esercizi 11 - API/tutorial/styles.css
Normal file
@@ -0,0 +1,116 @@
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #f0f2f5;
|
||||
color: #333;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #1a73e8;
|
||||
}
|
||||
|
||||
.controls {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
z-index: 100;
|
||||
background-color: white;
|
||||
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 12px 24px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
background-color: #1a73e8;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
margin: 5px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.1s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
button#btn-reset {
|
||||
background-color: #ea4335;
|
||||
}
|
||||
|
||||
.step-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
border-left: 6px solid #1a73e8;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.step-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
color: #1557b0;
|
||||
}
|
||||
|
||||
.step-desc {
|
||||
font-size: 0.95em;
|
||||
color: #5f6368;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.output-box {
|
||||
background: #2d3436;
|
||||
color: #00c900;
|
||||
padding: 10px;
|
||||
font-family: 'Courier New', monospace;
|
||||
border-radius: 6px;
|
||||
min-height: 20px;
|
||||
white-space: pre-wrap;
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.output-box.loading::after {
|
||||
content: "⏳ Attesa server...";
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
font-size: 0.8em;
|
||||
color: #e5c07b;
|
||||
}
|
||||
|
||||
.output-box.error {
|
||||
border: 2px solid #e06c75;
|
||||
color: #e06c75;
|
||||
}
|
||||
|
||||
.output-box.success {
|
||||
border-left: 4px solid #98c379;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 0.8em;
|
||||
color: #bbbbbb;
|
||||
margin-bottom: 5px;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
Reference in New Issue
Block a user