Служба Force AngularJS возвращает данные перед загрузкой контроллера
У меня есть служба в Angular, которая использует мой API для получения информации о пользователе и предоставляет ее моим контроллерам. Он настраивается следующим образом:
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource', 'infinite-scroll', 'ui.bootstrap', 'ngCookies', 'seo'])
.service('userInfo', function($http, $cookies){
$http.get('/api/users/' + $cookies.id).
success(function(data) {
var userInfo = data.user[0];
return userInfo;
});
}). // other stuff comes after this
В моих контроллерах я включаю его как:
function userProfile($scope, $cookies, userInfo, $http, $resource, $routeParams, $rootScope){
$scope.user = userInfo;
console.log('user info is')
console.log(userInfo);
Это не возвращает никаких данных, а если я поместил одну и ту же служебную функцию в сам контроллер, она вернется просто отлично. Что мне здесь не хватает? Никогда не использовались DI/Services в Angular, прежде чем это может быть простой ошибкой где-то.
Мне нужно убедиться, что служба возвращает данные до, которые загружаются контроллером. Как это можно сделать?
Ответы
Ответ 1
Вы можете сделать factory, чтобы вернуть такое обещание:
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource', 'infinite-scroll', 'ui.bootstrap', 'ngCookies', 'seo'])
.service('userInfo', function ($http, $cookies) {
var promise = $http.get('/api/users/' + $cookies.id).
success(function (data) {
var userInfo = data.user[0];
return userInfo;
});
return promise;
}) // other stuff comes after this
И в вашем контроллере сделайте
function userProfile($scope, $cookies, userInfo, $http, $resource, $routeParams, $rootScope){
userInfo.then(function(data){
$scope.user = data;
});
}
Это может гарантировать, что всякий раз, когда вы используете услугу, она всегда дает вам данные синхронно, вам не обязательно обязательно загружать данные перед загрузкой контроллера.
Ответ 2
Служба userInfo
должна вернуть обещание, возвращенное $http
. Это обещание будет затем введено в ваш контроллер, и представление будет обновляться, как только обещание будет успешно устранено.
Если вы не хотите, чтобы представление отображалось вообще до того, как userInfo
разрешилось, вы должны установить свойство resolve
на свой маршрут и ввести там свою службу:
$routeProvider.when('/profile', {
templateUrl: 'profile',
controller: userProfile,
resolve: {
userInfoData: function ($q, userInfo) {
return userInfo;
}
}
});
Затем просто введите userInfoData
в свой контроллер вместо службы userInfo
.
Ответ 3
Вы можете назначить объект ресурса своей переменной
return $http.get(url)
Ответ 4
Я столкнулся с той же проблемой, в которой мне приходилось загружать данные в службу с использованием ресурса $resource и получать эти данные в области контроллеров $.
Я не хотел напрямую возвращать обещание, а затем использовать резольвер в контроллере (как писал @zsong), но сделать все волшебство в службе один раз и использовать возможность назначить обещание непосредственно в $scope как @Joseph Сильбер указывает, вот что я сделал:
return function($scope){promise.then(function(data){$scope.user = data})};
И использовал его в контроллере следующим образом:
userInfo($scope);
Не так много улучшений, но это позволило мне более ясный синтаксис в моих контроллерах, надеюсь, что это поможет даже через три года!