Сервис $q и promise-объекты

Последнее обновление: 27.04.2017

Promise представляет результат выполения асинхронной операции. Promise-объект определяет методы, которые регистрируют функцию, вызываемую при завершении асинхронной операции. Переделаем предыдущий пример так, чтобы он использовал promise-объект и сервис $q. Файл с данными в формате json остается тем же самым. Вынесем все действия по загрузке данных в отдельный сервис. Пусть это будет файл dataService.js со следующим содержимым:

questApp.factory('dataService', function($http, $q){
	return{
		getData: function(){
			var deferred = $q.defer();
			$http({method: 'GET', url: 'question.json'}).
				then (function success(response) {
						deferred.resolve(response.data.question);
					},function error(response) {
						deferred.reject(response.status);
					}
				);
			
			return deferred.promise;
		}
	}
})

По сути этот сервис напоминает тот же, что делался в первой теме данной главы. В метод questApp.factory передаем название сервиса и функцию, принимающую два параметра - $http и $q. Далее в функции getData мы создаем deferred-объект: var deferred = $q.defer();

Суть создания deferred-объекта заключается в том, что он раскрывает, во-первых, api по выполнению операций. А во-вторых, он содержит ассоциированный promise-объект, и через deferred-объект мы взаимодействуем с promise-объектом. Чтобы получить promise-объект, в самом конце функции используется следующее выражение return deferred.promise.

Если запрос увенчался успехом, то вызываем метод deferred.resolve(data.question);. Этот метод сопоставляет данные с promise-объектом. В результате вызов return deferred.promise вернет нам загруженные данные.

Если запрос прошел неудачно, вызывается метод deferred.reject(status)

Контроллер у нас видоизменится следующим образом:

questApp.controller('QuestionController', 
	function QuestionController($scope, dataService){
	
		var promiseObj=dataService.getData();
        promiseObj.then(function(value) { $scope.question=value; });
		
		$scope.voteUp = function (answer){
			answer.rate++;
		};
		$scope.voteDown = function (answer){
			answer.rate--;
		};
	}
)

Поскольку в вышеопределенном сервисе функция getData возвращает promise-объект, который в свою очередь содержит все загруженные данные, то мы можем просто присвоить эти данные: var promiseObj=dataService.getData();

В тоже время важно понимать, что теперь promiseObj будет представлять не простой javascript-объект, а именно promise-объект, что накладывает некоторые ограничения на его использование.

Чтобы получить чистый javascript-объект, можно использовать функцию promiseObj.then, которая имеет следующий синтаксис: then(successCallback, errorCallback, notifyCallback)

Параметр successCallback представляет функцию, которая выполняется при удачном завершении действия. Функция, передаваемая в качестве параметра errorCallback, наоборот, выполняется при неудачном завершении действия. И функция, представленная параметром notifyCallback, может выполняться в качестве индикатора выполнения действия.

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

И в представлении index.html надо подключить созданный выше файл сервиса dataService.js:

<!doctype html>
<html ng-app="questApp">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/mystyles.css" />
</head>
<body>
<div  ng-controller="QuestionController">
<div class="content">
<div class="quest">
<h3>{{question.text}}</h3>
<p>{{question.author}} </p> <p><i>{{question.date}}</i></p>
</div>
<h3>Ответы</h3>
<div class="answers">
<div ng-repeat="answer in question.answers | orderBy:sortparam" class="answer">
<div class="vote">
    <a class="vote-up" ng-click="voteUp(answer)"></a>
    <span class="rate">{{answer.rate}}</span>
    <a class="vote-down" ng-click="voteDown(answer)"></a>
</div>
<b>{{answer.text}}</b>
<p>{{answer.author}}</p>
<p><i>{{answer.date}}</i></p>
</div>
</div>
</div>
<script src="js/lib/angular.min.js"></script>
<script src="js/app.js"></script>
<script src="js/dataService.js"></script>
<script src="js/controllers/QuestionController.js"></script>
</body>
</html>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850