До недавнего времени отправить или получить данные с сервера можно было с помощью форм с перезагрузкой страницы или с помощью AJAX без перезагрузки. Стандарт ES6 (EcmaScript2015) добавил технологию Fetch API, которая основана на промисах (Promises). Рассмотрим простой вариант получения данных с помощью Fetch API.
Что такое Fetch API?
В переводе с английского "fetch" - это получать, доставать, приносить. Т.е. Fetch API - это простой интерфейс для получения данных с ресурсов. Fetch позволяет нам сделать сетевой запрос и обрабатывать ответы проще, чем наш старый друг XMLHttpRequest (XHR). Одно из основных отличий заключается в том, что Fetch API использует промисы (Promises), что обеспечивает способ избежать большого количества обратных вызовов (так называемый callback hell) и типичного тяжелого кода, который предоставляет XMLHttpRequest (XHR).
Функция fetch()
принимает один обязательный аргумент - путь к ресурсу, который вы хотите получить, и возвращает Promise, который разрешается в ответе (response) этого запроса.
Теперь мы сталкиваемся с новым вопросом - а что такое промисы (Promises, или обещания)?
Что такое промисы?
Объект Promise представляет возможное завершение (или сбой) асинхронной операции и ее результирующее значение.
Промисы (Promises) в JavaScriptПромисы, или обещания предоставляют нам более простую альтернативу выполнению, составлению и управлению асинхронной операцией по сравнению с традиционным подходом на основе обратных вызовов.
Работая с промисами-обещаниями, мы должны знать, каково его текущее состояние, т.к. у этого объекта есть три состояния: Ожидание (Pending), Выполнено (Fulfilled ) и Отклонено (Rejected).
Когда Промис-Обещание находится в состоянии ожидания, оно может перейти в состояние Выполнено или Отклонено. Как только Обещание переходит в состояние Выполнено или Отклонено, оно не может перейти в любое другое состояние и его значение также не изменится (!).
Когда Обещание выполнено, это означает, что асинхронная операция завершена, и Обещание имеет значение. Когда Обещание отклонено, это означает, что асинхронная операция не удалась, и Обещание никогда не будет выполнено.
Использование Fetch API и Promis-ов
Теперь мы будем работать над простым примером, в котором мы будем использовать Fetch API и промисы, чтобы отобразить список, содержащий данные, загружаемые с удаленного ресурса. В качестве такого ресурса будем использовать общедоступный API с информацией от студии анимации под названием Studio Ghibli (https://ghibliapi.herokuapp.com/).
Запишем такой код:
1 2 3 4 |
const fetchPromise = fetch("https://ghibliapi.herokuapp.com/films"); fetchPromise.then(response => { console.log(response); }); |
Когда HTTP-запрос выполняется как асинхронная операция, выборка не возвращает никаких данных. Однако он вернет ответное Обещание. Когда мы регистрируем ответ, он покажет, что это Обещание находится в состоянии ожидания. Это означает, что ответ HTTP, который мы ожидаем, в конце концов вернется, но на момент регистрации этот ответ не был готов к регистрации.
Изначально наше Обещание находится в состоянии ожидания, но через некоторое время оно может перейти в выполненное состояние, если все идет хорошо, или в отклоненное состояние, если при загрузке произошла ошибка. Как только Обещание выполнено, оно больше не может изменять состояние.
Мы регистрируем ответ, чтобы увидеть, какую информацию мы получаем от API с помощью метода Promise.prototype.then(). В консоли браузера мы увидим объект Response (Ответ) с некоторой информацией, которая включает заголовки, текст, тип и даже код состояния.
Поскольку в объекте Response свойство status
имеет значение 200, а statusText
вернуло значение "OK", можно сделать вывод, что наш объект Promise перешел из состояния Pending (ожидание) в состояние Fulfilled (выполнено). Двигаемся дальше и пробуем извлечь данные о фильмах из ответа (response) нашего объекта Promise. Мы опять будем использовать метод промиса then()
, чтобы прикрепить обратный вызов, как только наше обещание будет выполнено.
Для того чтобы получить тело ответа в формате JSON, используем метод json()
для ответа вместо console.log()
. Эта операция также является асинхронной. Имейте ввиду, что метод json()
возвращает еще один Promise, поэтому нам нужно создать цепочку Обещаний с помощью такого кода:
1 2 3 4 5 6 |
const fetchPromise = fetch("https://ghibliapi.herokuapp.com/films"); fetchPromise.then(response => { return response.json(); }).then(films => { console.log(films); }); |
Мы передадим значение, полученное от первого Promise, в нашу цепочку, чтобы вывести информацию о фильмах студии в консоль. На данный момент их 20, и каждый фильм имеет свой id, title и description, а также данные о режиссере (director), продюсере (producer) и дате релиза фильма (release_date), что видно на скриншоте:
Вывод информации на html-страницу
Теперь нам просто нужно сформировать красивый html на основе полученной информации. Используем для форматирования вывода информации о фильмах компонент Card (Карточка) Bootstrap-4. Для разметки нам понадобится основной <div id="films">
и вложенные в него элементы <div class="container">
и <div class="row">
. Код видоизменится таким образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<div id="films"> <div class="container"> <h2 class="text-center mt-4">Heroku Films</h2> <div class="row"> </div> </div> </div> <script> const fetchPromise = fetch("https://ghibliapi.herokuapp.com/films"); let mainContent = '', main = document.querySelector('#films .row'); fetchPromise.then(response => { return response.json(); }).then(films => { films.forEach(film => { mainContent+=` <div class="col-md-6 film-heroku my-3"> <div class="card border-primary"> <div class="card-header bg-primary text-light"> <div class="card-title"> <h2>${film.title}</h2> <h4>Director: ${film.director}</h4> <h4>Producer: ${film.producer}</h4> <h4>Release Date: ${film.release_date}</h4> </div> </div> <div class="card-body" data-id="${film.id}"> <div class="card-text">${film.description}</div> </div> </div> </div>`; }); console.log(films); main.innerHTML = mainContent; }); </script> |
Результат можно посмотреть ниже или в новой вкладке:
Fetch API предоставил нам возможность загрузить данные достаточно быстро и с формированием структуры html-страницы на основе полученных JSON-данных. Этой технологией можно пользоваться в тех браузерах, которые поддерживают новые JS стандарты.
На основе статьи How to make HTTP requests using Fetch API and Promises
Cool!! Спасибо за ценную дополнительную инфу, респект ребята!