2014-12-18 2 views
4

Я уверен, что это будет легко для любого эксперта по Angular/Javascript. У меня есть служба, которая делает вызов к API, чтобы получить некоторые данные:Возврат данных http от Angular service

app.service("GetDivision", ["$http", function($http){ 

    this.division = function(divisionNumber){ 
    $http.post("/api/division", {division:divisionNumber}).success(function(data){ 
     return data; 
    }); 
    } 

}]); 

Теперь я называю это в одном из моих контроллеров, как так:

$scope.division = GetDivision.division(1); 

Однако моя служба не совсем правильно. Он не возвращает значение вне функции HTTP-запроса, поэтому данные не доходят до контроллера, вызывающего его. Как вернуть данные из запроса HTTP и вызванной функции?

+0

Потому что это асинхронный, то $ сфера получает данные до того, как вызов Ajax является полный. Вы можете использовать $ q в своем сервисе, чтобы создать обещание и вернуть его контроллеру, а контроллер получит результат в течение вызова() против обещаний. К вашим услугам, – AngularLover

ответ

8

Вам нужно понять, что вы не можете вернуться из асинхронных операций. Ответ просто не доступен, когда вы пытаетесь вернуть данные. Как правило, в Javascript вы должны использовать обратный вызов или шаблон обещания. Угловое обещание - очень естественный выбор.

app.service("GetDivision", ["$http", function($http) { 
    this.division = function(divisionNumber){ 
    return $http.post("/api/division", {division:divisionNumber}).success(function(data){ 
     return data; 
    }); 
    } 
}]); 

и в контроллере:

GetDivision.division(1).then(function(data) { 
    $scope.division = data; 
}); 

Убедитесь, что вы читаете эту очень популярную нить на тему: How do I return the response from an asynchronous call?

+0

Я думаю, что это самый правильный путь. – Rasalom

+0

согласны с вами :) – AngularLover

+0

@Rasalom. Ваш пример был также прекрасен, немного избыточен, так как '$ http.post()' уже возвращает объект Promise, поэтому не нужно использовать еще один '$ q.defer()'. – dfsq

1

Вы можете вернуть пустой объект от службы и заселить его, как только вы получаете ответ. Это способ $resource сервис сделать это. Это также позволяет избежать дополнительной логики в контроллере.

Это будет работать, потому что ссылка на объект data, который помещается в область действия, остается неизменным все время, и $http сервис начинает цикл дайджест после ответа ответа. Поэтому изменение в scope.division будет немедленно обнаружено, и просмотр будет соответствующим образом обновлен.

JavaScript

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

app.service("GetDivision", ["$http", function($http){ 

    var data = {}; 

    this.division = function(divisionNumber){ 
    $http.get("division", {division:divisionNumber}).success(function(responseData){ 
     angular.extend(data, responseData); 
    }); 
    return data; 
    } 

}]); 

app.controller('ctrl', ['$scope', 'GetDivision', function ($scope, GetDivision) { 
    $scope.division = GetDivision.division(1); 
}]); 

HTML

<body ng-controller="ctrl"> 
    <h1>{{division.text}}</h1> 
</body> 

Демо:http://plnkr.co/edit/H31mSaXiiCiVG9BA9aHK?p=preview

+0

Это тоже интересная идея. Однако я нахожу это довольно запутанным, так как неясно, почему он работает (для новичков, которые не знакомы с циклом дайджеста). В то же время надлежащее использование обещаний дает понять это, а также будет работать в неграмотном мире, потому что это всего лишь образец обещания. Но хорошая идея! – dfsq

Смежные вопросы