Отправляем запросы к API с помощью сервиса $http в AngularJS
AngularJS

Отправляем запросы к API с помощью сервиса $http в AngularJS

Оригинал: Making API Calls in AngularJS using Angular’s $http service, Tanay Pant

В настоящее время довольно распространена практика, когда веб-приложения взаимодействуют между собой с помощью API . К примеру, когда вы покупаете онлайн билет в кино, сайт обращается к удаленному API для проверки информации о вашей кредитной карте. В этом уроке я покажу, как, используя AngularJS, делать HTTP запросы к удаленному API и обрабатывать JSON ответы, обновляя представление.

Оставаяся в теме кино, я продемонстрирую это на примере просмотрщика информации о фильмах под названием Fastr, который будет получать различную информацию о каком-либо фильме, который вы введете. Кроме AngularJS для разработки Fastr будет использоваться Bootstrap для стилизации и Animate.css для некоторых визуальных эффектов.

В результате мы должны получить это:

Код проекта доступен на GitHub , а также вы можете посмотреть работающее демо на CodePen .

Структура проекта

Мы будет использовать следующую структуру файлов и папок в проекте:


css/
  animate.min.css
  bootstrap.min.css
  style.css
 
js/
  angular.min.js
  app.js
 
partials/
  main-info.html
  related-results.html
 
index.html

Файл index.html будет содержать главное представление приложения. В основном, здесь все стандартно, но давайте все же посмотрим детальнее:


<div class="input-group search-bar">
  <input type="text"
         ng-model="search"
         ng-change="change()"
         placeholder="Enter full movie name" />
  ...
</div>
 
<div id="main-info"
     ng-include="'partials/main-info.html'">
</div>
 
<div id="related-results"
     ng-include="'partials/related-results.html'">
</div>

Как вы можете видеть, мы использовали директиву ng-model, чтобы связать поле ввода (сюда пользователь будет вводить название фильма) с моделью search (которую мы объявим в контроллере). Мы также использовали директиву ng-change, чтобы каждый раз при изменении содержимого поля ввода вызывалась функция change() в контроллере. Эта функция будет отвечать за инициацию взаимодействия с удаленным API. Блоки main-info и related-results будут использоваться для отображения информации о текущем фильме и списка связанных фильмов. Информация будет отображаться в шаблонах, которые будут получены, скомпилированы и вставлены в представление с помощью директивы ng-include.

Вызов API для получения данных

Давайте взглянем на файл app.js  — сердце нашего приложения. Мы передаем $scope и $http в качестве параметров в конструктор контроллера. Тем самым мы объявляем зависимость от объекта scope и сервиса http .


.controller('MovieController', function($scope, $http) {

Когда страница только загрузилась, модель search неопределена. Поэтому мы устанавливаем значение «Sherlock Holmes» по умолчанию и вызываем метод fetch, который взаимодействует с API и гарантирует, что представление будет инициализировано.


if ($scope.search === undefined) {
    $scope.search = "Sherlock Holmes";
    fetch();
}

Далее мы определяем метод change. Он будет загружать результаты, когда значение в поле поиска изменится. Мы хотим, чтобы результаты загружались только спустя 800 миллисекунд после того, как пользователь прекратит ввод. Это предотвратит ненужные вызовы API в приложении. Также мы хотим видеть результат сразу же по мере ввода (не нажимая на Enter или кнопку поиска).


var pendingTask;
 
$scope.change = function() {
    if (pendingTask) {
        clearTimeout(pendingTask);
    }
    pendingTask = setTimeout(fetch, 800);
};

Теперь рассмотрим функцию fetch. Эта функция делает вызов API и обрабатывает JSON-ответ. Мы будем использовать в нашем приложении OMDb API  — бесплатный сервис, позволяющий получать информацию о фильмах. Если вам интересно, как работает API, вы можете ознакомиться с полной документацией по ссылке выше.

Чтобы отправить запрос, мы используем метод Angular $http.get, передаем адрес API, сконкатенированный со строкой запроса, в качестве параметра. Делаются два запроса к различным URL — первый для получения основной информации о фильме, а второй для получения связанных результатов.

В обработчиках success мы сохраняем результаты в моделях detail и related соответственно.


function fetch() {
    $http.get("http://www.omdbapi.com/?t=" + $scope.search + "&tomatoes=true&plot=full")
        .success(function(response) { $scope.details = response; });
 
    $http.get("http://www.omdbapi.com/?s=" + $scope.search)
        .success(function(response){ $scope.related = response; });
}

Далее посмотрим на функцию update. Она вызывается, когда пользователь щелкает по заголовку связанного фильма в представлении. Она принимает объект (содержащий информацию о выбранном фильме), устанавливает заголовок фильма в качестве значения поля поиска, при этом вызывается метод change и таким образом, наше приложение получает информацию об этом фильме.


$scope.update = function(movie){
    $scope.search = movie.Title;
    $scope.change();
};

И наконец, для большего удобства мы добавили функцию select, которая вызывается, когда пользователь устанавливает курсор в поле ввода.


$scope.select = function(){
    this.setSelectionRange(0, this.value.length);
}

Обработка ответа

Теперь давайте посмотрим файл partials/main-info.html .

Мы используем директиву ng-if, чтобы отобразить сообщение «Loading Results...», если данные еще не загружены, далее мы проверяем выражение details.Response === ‘True’, чтобы убедиться, что API нашел совпадение и вернул результат.

В случае, если результат есть, мы используем директиву ng-src, чтобы проверить значение details.Poster и либо загрузить картинку, которая находится в этом поле, либо отобразить картинку по умолчанию, если изображение не доступно.


<img ng-src="{{ details.Poster=='N/A' ? 
    'http://placehold.it/150x220&text=N/A' :
    'http://imdb.wemakesites.net/api/1.0/img/?url=' + details.Poster }}">

После этого мы отображаем остальные данные о фильме, в том числе еще четыре ссылки внизу страницы на внешние сайты, где пользователь может получить более подробную информацию о фильме. Мы отображаем эти ссылки, используя директиву ng-href, поскольку используем выражения Angular в атрибуте href и, если пользователь перейдет по ссылке раньше, чем Angular подставит значения выражений, все сломается.

Теперь посмотрим файл partials/related-results.html .


<div ng-if="related.Response!=='False'">
    Related Results:<hr>
 
    <ul class="rel-results">
        <li ng-repeat="movie in related.Search">
            <a href="#" id="{{ $index + 1 }}"
                ng-click="update(movie)">{{ movie.Title }}
            </a>, {{ movie.Year }}
        </li>
    </ul>
</div>

Здесь мы снова используем директиву ng-if, чтобы проверить, пришел ли ответ. Далее, используя директиву ng-repeat, мы проходим по элементам свойства Search модели related, которое содержит (кроме других вещей) список похожих результатов поиска.

Также мы иcпользуем директиву ng-click, чтобы вызвать метод контроллера update по клику на заголовок фильма. Как говорилось выше, эта функция выбирает и отображает информацию о новом фильме.

Заключительные штрихи

Мы можем добавить тег noscript в index.html, чтобы отобразить ошибку, если JavaScript выключен или не поддерживается браузером пользователя. Также мы можем подключить animate.css и добавить какие-нибудь клевые анимации, например, переворот постера, увеличение содержимого и подпрыгивание связанных результатов. Использовать animate.css довольно просто, нужно всего лишь добавить элементу соответствующий класс.


<div class="animated zoomInRight">

А вот и результат!

Пожалуйста, обратите внимание, что я спрятал связанные результаты во встроенном демо из-за нехватки места. Чтобы увидеть их, просто посмотрите демо на CodePen (в любом случае, это хорошая идея, так как демо там работает быстрее).

See the Pen YXXQxj by SitePoint (@SitePoint) on CodePen.

Заключение

В этом уроке я показал, как, используя AngularJS, сделать запрос к удаленному API и как использовать data-binding, чтобы немедленно обновить представление с результатами. Разработка проекта — это отличный способ изучить язык или какую-то особенность фреймворка, поэтому я призываю вас склонировать репозиторий и улучшить приложение.

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться