L'API builtin fetch, se hai letto l'articolo che ti ho linkato (uno dei primi che è venuto fuori con Google, forse non il migliore in effetti) è molto semplice da usare, basta avere chiaro il meccanismo di funzionamento.
Quando invii una richiesta HTTP ad un server, la risposta di questo non sarà immediata, ma ti arriverà dopo un certo ritardo che dipende da fattori esogeni (velocità della rete, carico di lavoro del server etc etc).
E' necessario quindi gestire questo meccanismo.
La differenza principale tra XMLHttpRequest e fetch è che, per gestire l'asincronismo implicito di una richiesta HTTP, la prima usa il meccanismo delle funzioni di callback associate ad eventi, mentre la seconda quello più moderno delle promise.
Se guardi con attenzione come è scritta la seguente funzione, hai un'idea chiara della sequenzialità delle operazioni:
- La funzione
fetch()
restituisce una promise, ovvero il prototipo di qualcosa che accadrà nell'immediato futuro. Quando questo "qualcosa" accadrà, il risultato sarà passato al successivo .then()
- Anche questo
.then()
restituisce una promise ovvero il parsing del JSON (è una promise, perché in fase di dichiarazione questo JSON ancora non esiste).
- Quando il primo
.then()
avrà processato il JSON ricevuto, passerà il risultato al successivo .then()
che a questo punto farà quel che deve con l'object ricevuto come parametro in ingresso (response.json()
ritorna un object JavaScript, se si trattava di testo semplice potevi usare response.text()
).
L'ultima riga invece è utile (ma non obbligatoria) per intercettare eventuali errori e gestirli (un JSON scritto male, l'indirizzo richiesto non esistente etc etc).
Puoi concatenare quanti .then()
vuoi e saranno sempre eseguiti in modo sequenziale: il blocco che segue riceve come parametri in ingresso il risultato del blocco che lo precede.
Ad esempio prova ad aggiungere questo .then(() => console.log('Tutte le operazioni precedenti sono state eseguite'))
e vedi come si comporta (usando i devTools del browser, tasto F12):
function getVals(){
fetch('/getVals') // Do the HTTP request (default GET)
.then(response => response.json()) // Parse the response as JSON
.then(obj => { // DO something with response
console.log(obj);
document.getElementById('val1').innerHTML = obj.val1;
document.getElementById('val2').innerHTML = obj.val2;
document.getElementById('val3').innerHTML = obj.val3;
})
.catch(err => console.log("Something went wrong!", err)); // Error handling
}
Lato Arduino, dovrai rispondere con questo famoso JSON da "costruire" a runtime con i valori dei sensori. La risposta dovrà informare il client che si tratta di testo formattato JSON e quindi deve contenere l'header Content-Type: application/json
(mentre tu adesso stai usando Content-Type: text/html
)
Puoi usare una libreria (come l'ottima ArduinoJSON) oppure visto che si tratta di poche righe, costruire la stringa pezzo per pezzo.
Un JSON è del semplice testo formattato secondo una logica {chiave: valore}
. se il valore è una stringa va racchiuso tra le virgolette "sono una stringa"
(quindi devi usare la combinazione con il carattere di escape \"
in C++), se invece è un valore numerico o booleano non serve.
{
"key1": val1,
"key2": val2,
"key3": val3
}
//Esempio Arduino:
int val1, val2, val3;
String json;
json += "{\"val1\": ";
json += val1;
json += ", \"val2\": ";
json += val2;
json += ", \"val3\": ";
json += val3;
json += "}";