- PVSM.RU - https://www.pvsm.ru -

Доступ к внешним API с помощью AngularJS(перевод статьи)

Оригинал статьи. [1]
AngularJS имеет простой способ взаимодействия с внешними API. В этой статье я рассмотрю, как использовать службы для доступа к API GitHub и создам простой обозреватель репозитория.

Шаг 1: Подготовка

Начну с простого HTML шаблона:

<!DOCTYPE html>
<html>
    <head>
        <title>GitHub Search</title>
    </head>
    <body>
    </body>
</html>

Добавлю AngularJS в head шаблона:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>

Немного CSS:

* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    font-family: sans-serif;
}
body, html { margin: 0; }
p { margin: 0; }
input { width: 100%; }
pre {
    white-space: pre-wrap;
    white-space: -moz-pre-wrap;
    white-space: -pre-wrap;
    white-space: -o-pre-wrap;
    word-wrap: break-word;
}
div.repo {
    border-bottom: 1px solid;
    cursor: pointer;
}
#search, #repo, #user { float: left; }
#search { width: 20%; }
#repo { width: 60%; }
#user { width: 20%; }

Шаг 2: Модуль

Модуль приложения:

var app = angular.module('githubsearch', []);

Добавлю его в шаблон с помощью директивы ngApp:

<body ng-app="githubsearch">

Шаг 3: Контроллер

Мне также понадобится контроллер для этого приложения. Для простоты, это будет один контролер для всего приложения, по этому мне не придется иметь дело с передачей информации между контроллерами:

app.controller('SearchController', function SearchController($scope) {
});

Шаг 4: Базовая служба

Определю базовую службу:

app.factory('GitHub', function GitHub($http) {
    return {
    };
});

Я использую метод app.factory(), чтобы просто вернуть объект с несколькими методами и использовать их позже. Я буду использовать $http для получения данных из API GitHub.

Шаг 5: Поиск репозитория

Первый метод в моем сервисе будет поиск репозитория с использованием API GitHub. Использование $http сервиса довольно просто (эта функция переходит в объект возвращенного нашей функции фабрики):

searchRepos: function searchRepos(query, callback) {
    $http.get('https://api.github.com/search/repositories', { params: { q: query } })
        .success(function (data) {
            callback(null, data);
        })
        .error(function (e) {
            callback(e);
        });
}

Метод $http.get() является сокращением от запросы GET. Первый параметр является URL, к которуму я хочу получить доступ. Второй является объектом с параметрами. Мне нужно только params объекта — это хэш параметров запроса, которые будут добавлены к запросу (параметр q является строкой поиска, как описано здесь [2]).

$http.get() возвращает promise [3]. Можно использовать success() и error () слушателей и вызвать соответствующую функцию.

Шаг 6: Блок поиска

Чтобы воспользоваться функцией, которую я создал в предыдущем шаге необходимо добавить поле поиска в html шаблон:

<div ng-controller="SearchController">
	<div id="search">
		<input ng-model="query" placeholder="search" ng-keyup="$event.keyCode == 13 && executeSearch()">
		<div class="repo" ng-repeat="repo in repos" ng-click="openRepo(repo.full_name)">
			<strong>{{ repo.full_name }}</strong>
			<p>{{ repo.description }}</p>
		</div> 			
	</div>   	
</div>

Я использую директиву ngModel для связи значение этого поля и переменную query и ngKeyup для вызова функцию executeSearch(), когда пользователь нажмет клавишу enter ($event.keyCode == 13). Использовать условные операторы в выражениях AngularJS нельзя, но простая логика операций будет работать.

Под полем ввода, я используя ngRepeat для отображения результатов поиска. Я буду выводить полное имя репозитория и описание (можно выводить разные данные, полный список можно посмотреть в API GitHub [4]).

Я также используем ngClick для вызова функцию openRepo() с полным описанием репозитория. Эту функция описана далее.

Шаг 7: Использование функции поиска

Теперь добавлю параметр GitHub к функции контроллера:

app.controller('SearchController', function SearchController($scope,GitHub) {

Функция executeSearch():

$scope.executeSearch = function executeSearch() {
    GitHub.searchRepos($scope.query, function (error, data) {
        if (!error) {
            $scope.repos = data.items;
        }
    });
}

Я вызываю метод GitHub.searchRepos() с параметром поиска $scope.query и помещаю результаты поиска (data.items) в переменную $scope.repos.

Это все, что нужно для вывода результатов поиска. Демо. [5]

Шаг 8: Получение информации о репозитории

Теперь, когда есть функция поиска можно вывести информацию о выбранном репозитории:

getRepo: function getRepo(name, callback) {
    $http.get('https://api.github.com/repos/'+ name)
        .success(function (data) {
            callback(null, data);
        })
        .error(function (e) {
            callback(e);
        });
    }

Название передаваемое в эту функцию должно быть полным именем (имя автора, слэш, имя репозитория — например: angular/angular.js), так как оно будет передано в API GitHub.

Шаг 9: Получение из репозитория README файл

Содержание файл README получу не в предыдущей функции, а в отдельной:

getReadme: function getReadme(name, callback) {
    $http.get('https://api.github.com/repos/'+ name +'/readme')
        .success(function (data) {
            callback(null, atob(data.content));
        })
        .error(function (e) {
            callback(e);
        });
}

Эта и предыдущая функция почти идентичны, только изменен URL. Еще использую функцию atob(), чтобы декодировать содержимое файла README, так как он кодирован в кодировке base64. Получение содержимого файла README описывается здесь [6].

Я не использовали два запроса в одной функции так как некоторые репозитории нет README файла.

Шаг 10: Отображение информации о репозитории

Я буду отображать полное имя репозитория, количество людей посмотревших его и файл README:

<div id="repo" ng-show="activeRepo">
    <strong>{{ activeRepo.full_name }}</strong> <em>Watched by {{ activeRepo.watchers_count }} people.</em>
    <pre>{{ activeRepo.readme }}</pre>
</div>

Хранить эту информацию я буду в переменной activeRepo. Директива ngShow покажет элемент, только если в нем есть данные.

Шаг 11: Обновление контроллера

Также необходимо обновить контроллер. Функция openRepo(), которую я повесил на директиву ngClick выше:

$scope.openRepo = function openRepo(name) {
    GitHub.getRepo(name, function (error, data) {
        if (!error) {
            $scope.activeRepo = data;
            GitHub.getReadme(name, function (error, data) {
                if (!error) {
                    $scope.activeRepo.readme = data;
                } else {
                    $scope.activeRepo.readme = 'No README found!';
                }
            });
        }
    });
}

Cначала я использую метод GitHub.getRepo(), для проверки на наличие ошибок, а затем помещаю данные в переменной activeRepo. После этого я и получаю файл README.

Демо 2 [7]

Автор: romasport

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/tutorial/68616

Ссылки в тексте:

[1] Оригинал статьи.: http://code.tutsplus.com/tutorials/accessing-external-apis-using-angularjss-services--cms-21884

[2] здесь: https://developer.github.com/v3/search/#parameters

[3] promise: https://docs.angularjs.org/api/ng/service/$q

[4] API GitHub: https://developer.github.com/v3/

[5] Демо.: http://codepen.io/romasport/pen/Kbtcg

[6] здесь: https://developer.github.com/v3/repos/contents/#get-the-readme

[7] Демо 2: http://codepen.io/romasport/pen/zcyJd

[8] Источник: http://habrahabr.ru/post/234451/