Introduzione alla funzione fetch()

Matt Gaunt

fetch() ti consente di effettuare richieste di rete simili a XMLHttpRequest (XHR). La differenza principale è che l'API Fetch utilizza Promises, che dispone di un'API più semplice per evitare i complessi callback nell'API XMLHttpRequest.

Supporto dei browser

  • 42
  • 14
  • 39
  • 10.1

Origine

Se non hai mai utilizzato Promise, consulta Introduzione alle promesse di JavaScript.

Richiesta di recupero di base

Ecco un esempio implementato con XMLHttpRequest e poi con fetch. Vogliamo richiedere un URL, ricevere una risposta e analizzarlo come JSON.

XMLHttpRequest

Un XMLHttpRequest ha bisogno di due listener per gestire i casi di successo e di errore e una chiamata a open() e send(). Esempio da documenti MDN.

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}

function reqError(err) {
    console.log('Fetch Error :-S', err);
}

var 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(
  function(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(function(err) {
    console.log('Fetch Error :-S', err);
  });

La richiesta fetch() richiede una sola chiamata per svolgere lo stesso funzionamento dell'esempio XHR. Per elaborare la risposta, prima controlliamo che lo stato della risposta sia 200, quindi analizzeremo la risposta come JSON. La risposta a una richiesta fetch() è un oggetto Stream, il che significa che dopo la chiamata del metodo json(), viene restituito un Promise. Il flusso avviene in modo asincrono.

Metadati delle risposte

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, come le intestazioni:

fetch('users.json').then(function(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 effettuiamo una richiesta di recupero, la risposta riceverà un valore 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 sulla 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 quest'ultima restituisce intestazioni COR, il tipo è cors. Le risposte di cors sono simili alle risposte 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 intestazioni CORS. Con una risposta opaca non saremo in grado di leggere i dati restituiti o visualizzare lo stato della richiesta, il che significa che non puoi verificare se la richiesta è andata a buon fine.

Puoi definire una modalità per una richiesta di recupero in modo che vengano risolti solo alcuni tipi di richiesta. Le modalità che puoi impostare sono le seguenti:

  • same-origin riesce solo per le richieste di asset nella stessa origine e rifiuta tutte le altre richieste.
  • cors consente le richieste per asset nella stessa origine e in altre origini che restituiscono le intestazioni COR appropriate.
  • cors-with-forced-preflight esegue un controllo preflight prima di effettuare qualsiasi richiesta.
  • no-cors è destinato a effettuare richieste ad altre origini che non hanno intestazioni CORS e generano una risposta opaque, ma, come indicato, al momento non è possibile nell'ambito globale della finestra.

Per definire la modalità, aggiungi un oggetto opzioni come secondo parametro nella richiesta fetch e definisci la modalità in tale oggetto:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
    .then(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(error) {
    log('Request failed', error)
    });

Concatenamento delle promesse

Una delle grandi caratteristiche delle promesse è la possibilità di collegarle tra loro. 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 codice JSON per ogni risposta. Puoi semplificare il codice definendo lo stato e l'analisi 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(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

In questo esempio viene definita 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 Promise si risolve, lo script chiama quindi il metodo json(), che restituisce una seconda Promise dalla chiamata response.json() e crea un oggetto contenente il JSON analizzato. Se l'analisi non va a buon fine, la proprietà Promise viene rifiutata ed 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 di fetch():

fetch(url, {
    method: 'post',
    headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
    })
    .then(json)
    .then(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

Invia 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'
})