fetch()
ti consente di effettuare richieste di rete simili a XMLHttpRequest (XHR). La
principale differenza è che l'API Fetch utilizza le promesse, che hanno un'API più semplice per aiutarti a evitare i complicati callback nell'
API XMLHttpRequest.
Se non hai mai utilizzato Promise prima, consulta Introduzione alle Promise di JavaScript.
Richiesta di recupero di base
Ecco un esempio implementato con un XMLHttpRequest
e poi con fetch
. Vogliamo richiedere un URL, ricevere una risposta e analizzarla come JSON.
XMLHttpRequest
Un XMLHttpRequest
ha bisogno di due ascoltatori per gestire i casi di successo
e di errore, nonché una chiamata a open()
e send()
.
Esempio tratto dalla documentazione MDN.
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
Recupero
La nostra richiesta di recupero ha il seguente aspetto:
fetch('./api/some.json')
.then(response => {
if (response.status !== 200) {
console.log(`Looks like there was a problem. Status Code: ${response.status}`);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
La richiesta fetch()
richiede una sola chiamata per eseguire la stessa operazione dell'esempio XHR. Per elaborare la risposta, controlliamo innanzitutto che lo stato della risposta sia 200, quindi analizziamo la risposta come JSON. La risposta a una richiesta fetch()
è un oggetto
Stream, il che significa che dopo
chiamare il metodo json()
viene restituita una promessa.
Lo stream avviene in modo asincrono.
Metadati della risposta
L'esempio precedente mostrava lo stato dell'oggetto Response e come analizzare la risposta come JSON. Ecco come gestire altri metadati a cui potresti voler accedere, ad esempio le intestazioni:
fetch('users.json').then(response => {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
Tipi di risposta
Quando viene effettuata una richiesta di recupero, alla risposta viene assegnato un response.type
di "basic
",
"cors
" o
"opaque
".
Questi types
mostrano la provenienza della risorsa e puoi utilizzarli per
determinare come trattare l'oggetto risposta.
Quando il browser richiede una risorsa nella stessa origine, la risposta ha un tipo basic
con limitazioni su ciò che puoi visualizzare dalla risposta.
Se viene effettuata una richiesta per una risorsa su un'altra origine e questa origine restituisce
intestazioni CORS, il tipo è cors
. Le risposte cors
sono simili a quelle basic
, ma limitano le intestazioni che puoi visualizzare a Cache-Control
, Content-Language
, Content-Type
, Expires
,
Last-Modified
e Pragma
.
Le risposte opaque
provengono da un'origine diversa che non restituisce le intestazioni CORS. Con una risposta opaca non potremo leggere i dati restituiti o visualizzare lo stato della richiesta, il che significa che non potrai verificare se la richiesta è andata a buon fine.
Puoi definire una modalità per una richiesta di recupero in modo che vengano risolti solo determinati tipi di richieste. Le modalità che puoi impostare sono le seguenti:
same-origin
ha esito positivo solo per le richieste di asset nella stessa origine e rifiuta tutte le altre richieste.cors
consente le richieste di asset nella stessa origine e in altre origini che resistono le intestazioni CORS appropriate.cors-with-forced-preflight
esegue un controllo preliminare prima di effettuare qualsiasi richiesta.no-cors
è progettato per inviare richieste ad altre origini che non hanno intestazioni CORS e generare una rispostaopaque
, ma, come indicato, al momento non è possibile nell'ambito globale della finestra.
Per definire la modalità, aggiungi un oggetto options come secondo parametro nella richiestafetch
e definisci la modalità in quell'oggetto:
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
Concatenamento di promesse
Una delle grandi funzionalità delle promesse è la possibilità di metterle in catena. Per
fetch()
, ti consente di condividere la logica tra le richieste di recupero.
Se utilizzi un'API JSON, devi controllare lo stato e analizzare il JSON per ogni risposta. Puoi semplificare il codice definendo lo stato e la parsing JSON in funzioni separate che restituiscono promesse e utilizzare la richiesta di recupero per gestire solo i dati finali e il caso di errore.
function status (response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json (response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
Questo esempio definisce una funzione status
che controlla response.status
e
restituisce una promessa risolta come
Promise.resolve()
o
una promessa rifiutata come
Promise.reject()
.
Questo è il primo metodo chiamato nella catena fetch()
.
Se la promessa viene risolta, lo script chiama il metodo json()
, che
restituisce una seconda promessa dalla chiamata response.json()
e crea un
oggetto contenente il JSON analizzato. Se l'analisi non riesce, la promessa viene rifiutata e viene eseguita l'istruzione catch.
Questa struttura ti consente di condividere la logica tra tutte le richieste di recupero, semplificando la gestione, la lettura e il test del codice.
Richiesta POST
A volte un'app web deve chiamare un'API con un metodo POST e includere alcuni parametri nel corpo della richiesta. Per farlo, imposta i parametri method
e body
nelle opzioni fetch()
:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
Inviare le credenziali con una richiesta di recupero
Per effettuare una richiesta di recupero con credenziali come i cookie, imposta il valore credentials
della richiesta su "include"
:
fetch(url, {
credentials: 'include'
})