Статьи

Выполнение API-вызовов в AngularJS с использованием сервиса Angular $ http

Примечание. Эта статья была обновлена ​​2016.01.17 пользователем Siyuan Hua.

  • Замененные ненужные вызовы setTimeout и clearTimeout заменены setTimeout clearTimeout ng-model-option и службой $watch .
  • .success() / .error() устарели, обновлены для использования вместо них .then(success_callback, error_callback) .
  • Исправить сломанное изображение плаката.

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

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

Вот чем мы закончим:

Снимок экрана приложения FASTR

Код для этого проекта доступен в нашем репозитории 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-model-options="{ debounce: 800 }" 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> в <div class="input-group search-bar"> <input type="text" ng-model="search" ng-model-options="{ debounce: 800 }" 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-model-options со значением debounce 800, чтобы гарантировать, что модель обновляется с задержкой не менее 800 мс. Мы также отслеживаем модель поиска изменений с помощью службы $watch и регистрируем обратный вызов для извлечения данных каждый раз, когда обнаруживается изменение. Вы увидите это в следующем разделе.

Диваны main-info и related-results будут использоваться для отображения информации о текущем фильме и списке связанных фильмов соответственно. Информация будет отображаться в партиалах, которые выбираются, компилируются и ng-include директиву ng-include .

Вызов API для данных

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

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

Теперь, когда страница загружается в первый раз, модель поиска не определена. Итак, мы установили для него «Шерлок Холмс» и fetch функцию fetch , которая свяжется с удаленным API и обеспечит инициализацию представления.

Теперь в MovieController мы настраиваем мониторинг модели search и загружаем результаты при изменении строки в окне поиска. Мы хотим, чтобы результаты выбирались только после того, как пользователь прекратил печатать в течение 800 миллисекунд (помните, что мы использовали директиву ngModelOptions со значением debounce 800). Это предотвращает ненужные обращения приложения к API. Мы также хотим видеть результаты мгновенно, когда мы печатаем (мы не хотим нажимать клавишу ввода или нажимать любую кнопку поиска).

 $scope.$watch('search', function() { fetch(); }); 

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

Затем мы инициализируем модель search для «Шерлока Холмса» в контроллере, который, в свою очередь, вызывает обратный вызов fetch() зарегистрированный в службе $watch , которая связывается с удаленным API и гарантирует, что представление инициализировано.

 $scope.search = "Sherlock Holmes"; 

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

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

В случае успеха мы сохраняем ответы в модели, называемой details и модели, называемой related соответственно.

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

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

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

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

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

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

Давайте теперь проанализируем файл partials / main-info.html .

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

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

 <img ng-src="{{ details.Poster=='N/A' ? 'http://placehold.it/150x220&text=N/A' : details.Poster }}"> 

После этого мы используем привязки данных Angular для отображения оставшихся деталей фильма, прежде чем включить четыре дальнейшие ссылки внизу страницы на внешние сайты, где пользователь может получить больше информации о фильме. Мы отображаем эти ссылки, используя директиву 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 модели, которое содержит (среди прочего) список названий фильмов, связанных с фильмом, который мы искали.

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

Некоторые последние штрихи

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

 <div class="animated zoomInRight"> 

И вот результат!

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

Вывод

В этом руководстве я продемонстрировал, как использовать AngularJS для запроса удаленного API и как использовать механизмы привязки данных Angular для немедленного обновления представления с результатами. Создание такого проекта может стать отличным способом изучения конкретного языка или фреймворка, поэтому я призываю вас клонировать репозиторий и улучшать приложение.