Ответ 1
Я могу придумать два способа сделать это. Первое, безусловно, лучше второго.
Первый способ: использование свойства resolve
маршрутов
Вы можете использовать свойство resolve
объекта конфигурации маршрута, чтобы указать, что обещание должно быть разрешено, и разрешенное значение будет использоваться для значения одной из ваших зависимостей между контроллерами, так что, как только ваш контроллер будет работать, значение сразу доступно.
Например, скажем, у вас есть следующая услуга:
app.service('things', ['$http', '$q', function ($http, $q) {
var deferred = $q.defer();
$http({
method: 'GET',
url: '/things',
cache: true
}).success(function (data) {
deferred.resolve(data);
}).error(function (msg) {
deferred.reject(msg);
});
return deferred.promise;
}]);
Затем вы можете определить свой маршрут примерно так:
$routeProvider.when('/things', {
controller: ['$scope', 'thingsData', function ($scope, thingsData) {
$scope.allThings = thingsData;
}],
resolve: {
thingsData: ['things', function (things) {
return things;
}]
}
});
Ключ в объекте resolve
соответствует имени второй зависимости для контроллера, поэтому, хотя он возвращает обещание, это обещание будет разрешено до запуска контроллера.
Второй способ: Сделайте запрос задолго до того, как вам понадобится данные
Второй способ, который совсем не идеален и, вероятно, в какой-то момент укусит вас на заднице, заключается в том, чтобы сделать запрос на данные на раннем этапе, например, когда ваше приложение инициализировано, а затем на самом деле получить позже, скажем, на странице, для которой требуется 3 щелчка, чтобы перейти с домашней страницы. Пальцы пересекаются, если звезды выровнены, ваш запрос HTTP будет возвращен к тому времени, и вы будете иметь данные для использования.
angular.module('myModule').factory('myService', ['$http', '$q', function($http, $q) {
var data = [];
function fetch() {
$http.get('/server/call').then(function (d) { data = d; });
}
// Public API
return {
fetchData: fetch,
myServiceCall: function () {
return data;
}
};
}]);
Затем в функции запуска модуля выполните запрос:
angular.module('myModule').run(['myService', function (myService) {
myService.fetchData();
});
Затем в контроллере для страницы, которая будет работать как минимум через 3 секунды после запуска приложения, вы можете сделать так, как вы предположили:
angular.module('myModule').controller('deepPageCtrl', ['$scope', 'myService', function ($scope, myService) {
$scope.data = myService.myServiceCall();
if (angular.isArray($scope.data) && $scope.data.length === 0) {
panic("data isn't loaded yet");
}
}]);
Бонус, одинаково плохой третий способ: Синхронный запрос AJAX
Сделайте так, как предлагает ricick, и используйте синхронный запрос AJAX с помощью метода jQuery .ajax()
.