Оглавление
Доброго времени суток, друзья. При разработке современных приложений (SPA) нельзя обойтись без запросов клиентской части на сервер. Для работы с сетевыми запросами в JavaScript используется термин AJAX (Asynchronous JavaScript And XML), который включает в себя набор технологий: HTML, XHTML, CSS, DOM, JavaScript, XMLHttpRequest, XML, XSLT. Для создания самих запросов использовался API XMLHttpRequest, сейчас уже он является устаревшим. JavaScript обладает более современным интерфейсом Fetch API, который появился для работы с HTTP одновременно с Service Worker’ами. Основная проблема, которую позволил решить Fetch API это отказ от большого количества callback’ов при использовании XMLHttpRequest и переходу к Promise (Обещания).
Метод fetch
Fetch API предоставляет метод fetch() для работы с запросами. Данный метод поддерживается всеми современными браузерами. Для работы со старыми браузерами требуются полифиллы. Рассмотрим подробнее метод fetch и его параметры.
Пример:
fetch(url, [options])
Первый параметр предназначен для указания url адреса к запрашиваемому серверу. Этот параметр является строкой или строковым выражением (с возможностью указания в ней параметров). Второй параметр является объектом, в котором можно указать множество дополнительных опций. Если записывать fetch без второго параметра, то мы получим простой GET запрос.
Пример:
fetch('http://example.com/api/users')
Данная запись возвращает Promise, специальный объект хранящий свое состояние. Для того, чтобы понять как с ним работать, давайте рассмотрим его более подробно.
Видео на эту тему.
Promise
Для работы с Promise в JavaScript есть два способа:
— then/catch
— async/await
Начнем с then, этот метод предназначен для навешивая обработчиков на Promise. Для получения ответа требуется вызвать метод then два раза.
Пример:
fetch('http://example.com/api/users')
.then((response) => {
return response.json();
})
.then((data) => {
console.log(data);
});
В первом then происходит получение объекта Response. Данный объект хранит в себе состояние нашего запроса.
Пример:
{
body: ReadableStream
,
bodyUsed: false
,
headers: Headers {},
ok: true,
redirected: false,
status: 200,
statusText: "",
type: "basic"
url: "http://example.com/api/users"
}
В примере выше можно посмотреть на основные поля ответа. Запрос выполнился со статусом 200 и состоянием ok, что означает true. Это означает что запрос был выполнен успешно и никаких ошибок не возникло.
Чтобы получить тело ответа, нужно воспользоваться специальным методом Response, посмотрим на его методы:
response.json() — декодирует ответ в JSON
response.text() — декодирует ответ в текст
response.formData() — вернет ответ в виде FormData
response.arrayBuffer() — вернет ответ в виде ArrayBuffer
response.blob() – вернет ответ в виде Blob
Важно. Можно использовать только один метод для обработки ответа. Повторный вызов другого метода приведет к ошибке.
Пример:
fetch(‘http://example.com/api/users')
.then((response) => {
response.text()
return response.json(); // Error!
})
.then((data) => {
console.log(data);
});
В нашем примере мы преобразуем ответ в JSON формат. После вызова первого then и применения метода объекта Response, в результате мы получаем Promise, для обработки которого снова требуется вызвать метод then. Результатом последующего вызова then будет получение тела нашего запроса.
Метод catch
Для обработки ошибок в Promise вместе с then используется метод catch.
Пример:
fetch('http://example.com/api/users')
.then((response) => {
response.text()
return response.json(); // Error!
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error)
})
Внутри catch достаточно вызвать колбэк функцию, в аргументе которой мы получим тело ошибки для ее дальнейшей обработки.
async/await
Второй, более современный и лаконичный способ работы с Promise является использование async/await. Перепишем наш предыдущий пример GET запроса.
Пример:
async function getUsers() {
let response = await fetch('http://example.com/api/users');
if (response.ok) {
let data = await response.json();
console.log(data);
return data
} else {
alert('error', response.status);
}
}
getUsers();
В данном примере для обработки ошибок идет проверка на состояние объекта Response. Для работы с ошибками в async/await существует более эстетичное решение с использованием конструкции try..catch
Пример:
async function getUsers() {
try {
let response = await fetch('http://example.com/api/users');
let users = await response.json();
return users;
} catch(error) {
alert(error);
}
}
getUsers();
Заголовки запросов
Использование метода fetch дает возможность работать с заголовками. Для получения заголовка ответа, достаточно при получении объекта Response вызвать свойство headers и воспользовавшись методом .get() достать из него нужный заголовок.
Пример:
let response = await fetch('http://example.com/api/users');
response.headers.get('Content-Type');
Для передачи заголовка запроса, необходимо воспользоваться вторым параметром метода fetch и передать в него объект headers. Например, установим Content-Type со значением application/json.
Пример:
let response = fetch('http://example.com/api/users', {
headers: {
"Content-Type": "application/json"
}
})
POST запрос
Вот так плавно мы перешли к использованию второго параметра метода fetch. Помимо получения данных с сервера частой задачей является отправление данных на сервер. Для этого требуется указать в объекте опций поле method и передать тело запроса body (если используется json формат, а не передача значений через url параметры) с указанием заголовка в headers.
Пример:
let user = {
name: 'Dima'
};
let response = await fetch('http://example.com/api/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(user)
});
let result = await response.json();
В примере при получении объекта user используется JSON.stringify для преобразования значения в строку JSON. Заголовок «Content-Type»: «application/json; charset=utf-8» явно указывает передачу на сервер формата JSON.
Описание Options
Напоследок пройдем по всем опциям второго параметра fetch.
let response = fetch('http://example.com/api/user', {
method: «GET"
headers: {
"Content-Type": "text/plain;charset=UTF-8"
},
body: undefined
referrer: "http://example.com/api/user",
referrerPolicy: "no-referrer-when-downgrade",
mode: "cors",
credentials: "same-origin"
cache: "default"
redirect: "follow",
integrity: "",
keepalive: false,
signal: undefined,
window: window
})
method — этот параметр мы уже разбирали выше. В нем мы указываем заголовок метода, с которым будем отправлять запрос ( «GET», «POST», «PUT», «DELETE» и другие).
headers — заголовки запроса. Зависит от тела запроса и обычно ставится автоматически.
body — тело запроса. Может быть FormData, BufferSource, URLSearchParams или string.
referrer — данный параметр отвечает за установку HTTP-запроса заголовка Referer. Как правило он устанавливается самостоятельно, без явного его указания. Можно не отправлять заголовок Referer, указав его значение как пустую строку «».
referrerPolicy — этот параметр устанавливает общие правила для Referer. Для более подробной информации воспользуйтесь официальной спецификацией.
mode — защита от отправки запросов на другой сервер. Mode имеет несколько значений:
— «no-cors» — разрешение простых запросов на другой сервер;
— «cors» — установлен по умолчанию. Позволяет делать запросы разреженной CORS политикой сервера;
— «same-origin» — запрос на другие сервера запрещен.
credentials — данный параметр указывает должен ли fetch отправлять куки и авторизованные заголовки вместе с HTTP-запросом. Имеет следующие значения:
— «omit» — всегда не отправлять
— «same-origin» — по умолчанию, не отправлять для запросов на другой сервер
— «include» — отправлять всегда
cache — этот параметр позволяет указывать использовать или не использовать стандартное HTTP-кэширование. Имеет следующие значения:
— «only-if-cached» — использовать ответ из HTTP-кэша. Если ответа нет, то ошибка.
— «force-cache» — использовать ответ из HTTP-кэша. Если ответа нет, то сделать обычный HTTP-запрос.
— «no-cache» — сохраняет ответ в HTTP-кэш.
— «reload» — не брать результат из HTTP-кэша.
— «no-store» — игнорировать HTTP-кэш
— «default» — стандартное поведение и использование HTTP-кэша по умолчанию.
redirect — отвечает за политику выполнения стандартного HTTP-редиректа. Имеет следующие значения:
— «manual» — не следовать HTTP-редиректу
— «error» — ошибка если произойдёт HTTP-редирект
— «follow» — по умолчанию, следовать HTTP-редиректу
integrity — проверка соответствия ответа контрольной сумме.
keepalive — данный параметр указывает на то, что запрос может пережить страницу, которая его запросила. Имеет всего два значения (true/false)
signal — прерывание запроса.
window — можно передать глобальный объект window. В современных приложениях используется крайне редко.
Заключение
В данной статье мы подробно рассмотрели интерфейс Fetch API и его метод fetch. Поработали с Promises. Изучили обработчики обещаний, используя методы then/catch и специальный синтаксис async/await. Прошлись по основным параметрам метода fetch и подробно разобрали его опции. Надеюсь, что данный материал был вам полезен. Учитесь, думайте, пишите код. Удачного кодинга, друзья!
Полезные материалы:
https://learn.javascript.ru/fetch — документация Fetch
https://developer.mozilla.org/ru/docs/Web/API/Fetch_API/Using_Fetch — документация Fetch
Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации.
позволяет вам делать запросы, схожие с XMLHttpRequest (XHR). Основное отличие заключается в том, что Fetch API использует Promises (Обещания), которые позволяют использовать более простое и чистое API, избегать катастрофического количества callback’ов и необходимости помнить API для XMLHttpRequest. Fetch API стал доступен пользователям вместе с Service Worker ‘ами в global скоупе в Chrome 40, однако уже в версии 42 он станет доступен в скоупе window. Разумеется, для всех остальных браузеров, которые пока ещё не поддерживают fetch существует полифил от GitHub, который доступен уже сегодня. Первым делом мы проверяем статус ответа и проверяем, успешно ли выполнился запрос (ожидаем 200 статус). Если всё хорошо, то парсим ответ как JSON. Ответом