Wprowadzenie do pobierania()

fetch() umożliwia wysyłanie żądań sieciowych podobnych do XMLHttpRequest (XHR). Główna różnica polega na tym, że interfejs Fetch API korzysta z obiektu Promises, który ma prostszy interfejs API, dzięki czemu można uniknąć skomplikowanych wywołań zwrotnych w interfejsie XMLHttpRequest API.

Obsługa przeglądarek

  • Chrome: 42.
  • Edge: 14.
  • Firefox: 39.
  • Safari: 10.1

Źródło

Jeśli nigdy wcześniej nie korzystałeś(-aś) z obietnic, przeczytaj artykuł Wprowadzenie do obietnic w JavaScriptzie.

Oto przykład implementacji za pomocą tagów XMLHttpRequest, a potem fetch. Chcemy wysłać żądanie do adresu URL, uzyskać odpowiedź i przeanalizować ją jako dane JSON.

XMLHttpRequest

XMLHttpRequest wymaga 2 detektorów do obsługi przypadków sukcesu i błędów oraz wywołania open() i send(). Przykład z dokumentacji 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();

Pobierz

Nasze żądanie pobierania wygląda tak:

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);
  });

Żądanie fetch() wymaga tylko 1 wywołania, aby wykonać tę samą pracę co przykład XHR. Aby przetworzyć odpowiedź, najpierw sprawdzamy, czy ma ona stan 200, a następnie analizujemy ją w formacie JSON. Odpowiedź na żądanie fetch() to obiekt Stream, co oznacza, że po wywołaniu metody json() zwracana jest obietnica. Transmisja odbywa się asynchronicznie.

Metadane odpowiedzi

Poprzedni przykład pokazał stan obiektu Response oraz sposób parsowania odpowiedzi w formacie JSON. Oto jak obsługiwać inne metadane, do których chcesz uzyskać dostęp, np. nagłówki:

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);
});

Typy odpowiedzi

Gdy wysyłamy żądanie pobierania, odpowiedź będzie miała response.type basic", "cors" lub "opaque". Te types pokazują, skąd pochodzi zasób. Możesz ich użyć, aby określić, jak traktować obiekt odpowiedzi.

Gdy przeglądarka żąda zasobu z tego samego źródła, odpowiedź ma typ basic z ograniczeniami dotyczącymi tego, co możesz wyświetlić.

Jeśli żądanie dotyczy zasobu w innym punkcie początkowym, które zwraca nagłówki COR, typ to cors. Odpowiedzi cors są podobne do odpowiedzi basic, ale ograniczają nagłówki, które możesz wyświetlić, do Cache-Control, Content-Language, Content-Type, Expires, Last-Modified i Pragma.

Odpowiedzi opaque pochodzą z innego źródła, które nie zwraca nagłówków CORS. W przypadku nieprzezroczystej odpowiedzi nie będziemy mogli odczytać zwróconych danych ani wyświetlić stanu żądania, co oznacza, że nie będzie można sprawdzić, czy żądanie zostało zrealizowane.

Możesz zdefiniować tryb żądania pobierania, aby były przetwarzane tylko niektóre typy żądań. Dostępne tryby:

  • same-origin działa tylko w przypadku żądań dotyczących komponentów z tego samego źródła i odrzuca wszystkie pozostałe żądania.
  • cors zezwala na żądania dotyczące zasobów w tym samym źródle i innych źródłach, które zwracają odpowiednie nagłówki CORS.
  • cors-with-forced-preflight przeprowadza kontrolę wstępną przed wysłaniem jakiegokolwiek żądania.
  • no-cors ma na celu wysyłanie żądań do innych źródeł, które nie mają nagłówków CORS, i zwracać odpowiedź opaque, ale jak już powiedzieliśmy, obecnie nie jest to możliwe w ramach globalnego zakresu okna.

Aby zdefiniować tryb, dodaj obiekt opcji jako drugi parametr w żądaniu fetch i zdefiniuj tryb w tym obiekcie:

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)
  });

Łańcuch obietnic

Jedną z największych cech obietnic jest możliwość ich połączenia. W przypadku fetch() umożliwia to współdzielenie logiki między żądaniami pobierania.

Jeśli używasz interfejsu API JSON, musisz sprawdzić stan i przeanalizować dane JSON dla każdej odpowiedzi. Aby uprościć kod, określ stan i analizę danych JSON w osobnych funkcjach, które zwracają obietnice, a potem użyj żądania pobierania do obsługi tylko końcowych danych i przypadków błędu.

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);
  });

W tym przykładzie zdefiniowano funkcję status, która sprawdza obiekt response.status i zwraca rozwiązaną obietnicę jako Promise.resolve() lub odrzuconą obietnicę jako Promise.reject(). Jest to pierwsza metoda wywoływana w łańcuchu fetch().

Jeśli obietnica zostanie spełniona, skrypt wywoła metodę json(), która zwraca drugą obietnicę z wywołania response.json() i tworzy obiekt zawierający przetworzony plik JSON. Jeśli analiza się nie uda, obietnica jest odrzucana i wykorzystywana jest instrukcja typu „catch”.

Taka struktura umożliwia współużytkowanie logiki we wszystkich żądaniach pobierania, co ułatwia obsługę, odczytywanie i testowanie kodu.

Żądanie POST

Czasami aplikacja internetowa musi wywołać interfejs API za pomocą metody POST i umieścić w treści żądania pewne parametry. Aby to zrobić, ustaw parametry method i body w opcjach 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);
  });

Wysyłanie danych logowania z żądaniem pobierania

Aby wysłać żądanie pobierania za pomocą danych uwierzytelniających takich jak pliki cookie, ustaw wartość credentials żądania na "include":

fetch(url, {
  credentials: 'include'
})