Inviare richieste al server via javascript e caricare nuove informazioni ogni volta che è necessario

Il metodo fetch()

Se state scrivendo un’applicazione web, è probabile che dobbiate lavorare con dati esterni, JavaScript può inviare richieste al server e caricare nuove informazioni ogni volta che è necessario.

Ad esempio, possiamo effettuare una richiesta per inviare un ordine o caricare le informazioni di un articolo etc… Tutto senza dover ricaricare la pagina.

Ci sono diversi modi per effettuare una richiesta ed ottenere informazioni dal server, nel nostro caso vedremo il metodo fetch().

Il metodo fetch() è moderno e versatile non è supportato dai vecchi browser, ma è molto ben supportato tra quelli moderni.

La sintassi base è:

let promise = fetch(url, [options])
  • url: indentifica l’URL a cui accedere;
  • options: parametri opzionali come headers, metodi etc..

Senza le options è una semplice richiesta GET.

Il browser avvia subito la richiesta e restituisce una promessa che il codice chiamante deve utilizzare per ottenere il risultato, la promessa (promise), restituita dal metodo fetch, si risolve con un oggetto Response non appena il server risponde con l’headers. A questo punto possiamo controllare lo status HTTP per capire se la richiesta è andata a buon fine o meno ma senza il body.

Possiamo vedere l’HTTP status nelle proprietà:

  • status: codice di stato HTTP, ad es. 200;
  • ok: booleano, vero se il codice di stato HTTP è 200-299.

let response = await fetch(url);

if (response.ok) { // se lo status HTTP è 200-299
  // prende il body
  let json = await response.json();
} else {
  alert("HTTP-Error: " + response.status); //restituisce l'errore
}

Per recuperare il body abbiamo bisogno di chiamare un altro metodo, la Response molteplici metodi basati su promise per accedere al corpo in vari formati:

  • response.text(): la risposta e restituirla come testo;
  • response.json(): la risposta come JSON;
  • response.formData(): restituisce la risposta come oggetto FormData;
  • response.blob(): risposta come Blob (dati binari con tipo);
  • response.arrayBuffer(): risposta come ArrayBuffer (rappresentazione a basso livello di dati binari);
  • in aggiunta, response.body  permette di leggere il corpo pezzo per pezzo.

Ad esempio volendo prendere l’oggetto JSON dell’ultimo commit da GitHub usando l’await:

let url = 'https://api.github.com/repos/xxxxx/yyyy/commits';
let response = await fetch(url);

let commits = await response.json();

alert(commits[0].author.login);

Oppure senza await ma usando il promise:

fetch('https://api.github.com/repos/xxxx/yyyy/commits')
  .then(response => response.json())
  .then(commits => alert(commits[0].author.login));

L’importante è ricordare che possiamo scegliere solo tra uno dei metodi per leggere il body, se abbiamo già usato il response.text() e poi il response.json() il secondo non funzionerà perchè il contenuto del body è stato già processato.

 

Di seguito un esempio completo di una richiesta a git per il recupero della cover:

fetch(`https://api.github.com/users/${name}`).then(
successResponse => {
if (successResponse.status != 200) {
return null;
} else {
return successResponse.json();
}
},
failResponse => {
return null;
}
).then(result => {
  document.write(result.avatar_url);
});

Passaggio dei dati ad una richiesta POST

Per una richiesta POST, è possibile utilizzare la proprietà “body” per passare una stringa JSON come input.

// dati da inviare tramite una richesta POST
let _data = {
  title: "foo",
  body: "bar", 
  userId:1
}

fetch('https://xxxx.yyyy.com/posts', {
  method: "POST",
  body: JSON.stringify(_data),
  headers: {"Content-type": "application/json; charset=UTF-8"}
})
.then(response => response.json()) 
.then(json => console.log(json));
.catch(err => console.log(err));