Обеспечение загрузки одного контроллера AngularJS перед другим

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

У меня есть система учетных записей пользователей, использующая OAUTH2, которая ищет информацию о пользователе в моей базе данных и сохраняет ее как переменную $rootScope.userInfo. Это находится в контроллере, который добавляется к моему приложению body; здесь я думал, что контроллер верхнего уровня будет загружаться до тех, кто живет внутри него, но, по-видимому, нет.

Если я загружу представление, которое пытается получить доступ к этому объекту $rootScope.userInfo, прежде чем мой mainCtrl имел возможность загрузить его из моей базы данных, он выдает ошибку javascript и Angular breaks.

Для справки, вот приблизительная идея шаблона:

<header>Content</header>
 <div ng-controller="userProfile">
 <p>{{user.name}}</p>
 <p>{{user.email}}</p>
 </div>

Я загружаю $rootScope.userInfo в mainCtrl следующим образом:

$http.get('/api/users/' + $cookies.id).
 success(function(data) {
 $rootScope.userInfo = data.user[0];
 console.log("User info is:");
 console.log($rootScope.userInfo);
 $scope.status = 'ready';
 });

Затем для моего элемента управления userProfile выполните следующие действия:

function userProfile($scope, $cookies, $http, $routeParams, $rootScope){
 if($scope.status == 'ready'){
 $scope.user = $rootScope.userInfo;
 console.log("****** checking user info, here it is:");
 console.log($rootScope.userInfo);
 }
}

Если я прихожу с другой страницы в приложении, которое не вызывает $rootScope.userInfo, API имеет достаточно времени, чтобы просмотреть его, а моя страница userProfile работает нормально. Однако, если вы выполняете полностраничное обновление, $rootScope.userInfo не имеет времени для загрузки, и я получаю ошибки.

Как я могу это исправить?

2 ответа

Проблема, которую вы описываете, является одной из причин, по которой не рекомендуется обмениваться данными между контроллерами с помощью $rootScope: он создает ручную "невидимую" зависимость между двумя контроллерами, которую вы должны вручную исправлять, когда конечный пользователь hasn еще не прошел через другой контроллер.

Рекомендуемое решение - переместить логику загрузки пользователя в службу, скажем userProfileService, которую вы вводите в оба контроллера, которые в ней нуждаются. Затем он будет создан один раз и будет использоваться для обоих контроллеров. В такой службе вы можете загрузить профиль пользователя с помощью $http, когда контроллер запросит его, и вернет его из кеша, когда следующий сделает. Таким образом, зависимость идет от обоих контроллеров к общей службе, а не от одного контроллера к другому.

Я не большой поклонник документации AngularJS, но они могут помочь: DI, Создание сервисов и Инъекционные услуги.


Используйте then вместо успеха и задерживайте загрузку дочернего контроллера с помощью ng-include:

<header>Content</header>

Переместите HTML внутри нового шаблона userprofile.html:

<div ng-controller="userProfile">
 <p>{{user.name}}</p>
 <p>{{user.email}}</p>
</div>

Обратный вызов внутри mainCtrl:

$http.get('/api/users/' + $cookies.id).
 then(function(data) {
 /* mainCtrl being the parent controller, simply exposing the 
 properties to $scope would make them available 
 to all the child controllers.*/
 $rootScope.userInfo = data.user[0];
 /* assign the template path to load the template and 
 instantiate the controller */
 $scope.templatePath = "userprofile.html";
 });

licensed under cc by-sa 3.0 with attribution.