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.
Jeśli nigdy wcześniej nie korzystałeś(-aś) z obietnic, przeczytaj artykuł Wprowadzenie do obietnic w JavaScriptzie.
Podstawowe żądanie pobierania
Oto przykład implementacji za pomocą elementu XMLHttpRequest
, a następnie za pomocą elementu fetch
. Chcemy wysłać żądanie do adresu URL, uzyskać odpowiedź i przeanalizować ją jako dane JSON.
XMLHttpRequest
Funkcja XMLHttpRequest
wymaga 2 słuchaczy do obsługi przypadków powodzenia i błędów oraz wywołania funkcji 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 jej stan to 200, a potem parsujemy ją jako dane 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 z innego źródła i to źródło zwraca nagłówki CORS, typ jest cors
. Odpowiedzi cors
są podobne do odpowiedzi basic
, ale ograniczają widoczne nagłówki 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 niepełnej 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 rozwiązywanie dotyczyło tylko określonych typów żą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 sprawdzenie wstępne przed wysłaniem żą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 najlepszych funkcji obietnic jest możliwość łączenia ich ze sobą. W przypadku fetch()
umożliwia to udostępnianie logiki w ramach żądań pobierania.
Jeśli pracujesz z interfejsem JSON API, musisz sprawdzić stan i przeanalizować dane JSON dla każdej odpowiedzi. Możesz uprościć kod, definiując stan i analizowanie JSON-a w osobnych funkcjach, które zwracają obietnice, a do obsługi tylko danych końcowych i błędów używać żądania fetch.
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 zdefiniowana jest funkcja status
, która sprawdza response.status
i zwraca albo spełnioną obietnicę jako Promise.resolve()
, albo 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 parsowanie się nie powiedzie, obietnica zostanie odrzucona, a wyrażenie catch zostanie wykonane.
Ta struktura umożliwia udostępnianie logiki we wszystkich żądaniach pobierania, co ułatwia utrzymanie, czytanie i testowanie kodu.
Żądanie POST
Czasami aplikacja internetowa musi wywołać interfejs API za pomocą metody POST i umieścić niektóre parametry w treści żądania. 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 z danymi logowania, takimi jak pliki cookie, ustaw wartość parametru credentials
na "include"
:
fetch(url, {
credentials: 'include'
})