2013-08-22 31 views
6

Tôi sẽ mở đầu điều này với thực tế là tôi thực sự không biết nếu đây là cách tốt nhất để đạt được những gì tôi đang làm và tôi rất cởi mở với những đề xuất tốt hơn.Đảm bảo một bộ điều khiển AngularJS tải trước

Tôi có hệ thống tài khoản người dùng sử dụng OAUTH2 để tìm kiếm thông tin người dùng trong cơ sở dữ liệu của tôi và lưu nó dưới dạng biến, $rootScope.userInfo. Điều này nằm trong một bộ điều khiển được gắn vào ứng dụng của tôi body; ở đây tôi đã nghĩ rằng bộ điều khiển mức cao nhất sẽ tải trước những người sống bên trong nó, nhưng rõ ràng là không.

Nếu tôi tải chế độ xem cố gắng truy cập đối tượng $rootScope.userInfo này trước khi mainCtrl của tôi có cơ hội tải nó vào từ cơ sở dữ liệu của tôi, nó sẽ phát ra lỗi javascript và lỗi Angular.

Để tham khảo, đây là một ý tưởng thô của mẫu:

<body ng-controller="mainCtrl"> 
    <header>Content</header> 
    <div class='main-view' ng-controller="userProfile"> 
     <p>{{user.name}}</p> 
     <p>{{user.email}}</p> 
    </div> 
</body> 

Tôi tải $rootScope.userInfo trong mainCtrl như thế này:

$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'; 
    }); 

Sau đó, để kiểm soát userProfile của tôi, tôi làm:

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

Nếu tôi đến từ một trang khác trong ứng dụng wh ich không gọi số $rootScope.userInfo, API có đủ thời gian để tìm kiếm và trang userProfile của tôi hoạt động tốt. Tuy nhiên, nếu thực hiện làm mới toàn bộ trang, thì $rootScope.userInfo không có thời gian tải và tôi gặp lỗi.

Làm cách nào để khắc phục sự cố này?

Trả lời

14

Vấn đề bạn mô tả là một trong những lý do tại sao nó không được khuyến khích chia sẻ dữ liệu giữa các bộ điều khiển bằng cách sử dụng $rootScope: nó tạo ra sự phụ thuộc "vô hình" thủ công giữa hai bộ điều khiển, rằng bạn phải khắc phục thủ công khi người dùng cuối không đi qua bộ điều khiển khác.

Giải pháp được khuyến nghị là di chuyển logic tải người dùng vào dịch vụ, giả sử userProfileService, mà bạn đưa vào cả hai trình điều khiển cần nó. Sau đó nó sẽ được tạo một lần và được sử dụng cho cả hai bộ điều khiển. Trong một dịch vụ như vậy bạn có thể tải hồ sơ người dùng với $http khi một bộ điều khiển yêu cầu nó, và trả lại nó từ bộ nhớ cache khi tiếp theo. Bằng cách này, sự phụ thuộc đi từ cả hai bộ điều khiển đến một dịch vụ chia sẻ, thay vì từ một bộ điều khiển này sang bộ điều khiển khác.

Tôi không phải là người hâm mộ lớn của tài liệu AngularJS, nhưng chúng có thể giúp: DI, Creating ServicesInjecting Services.

+0

Điều này khá gần, tôi thích ý tưởng sử dụng nó như một dịch vụ. Tuy nhiên nó không giải quyết được vấn đề trật tự tải. Tôi đã thiết lập dịch vụ, nhưng nó vẫn tải bộ điều khiển trước khi dịch vụ đã trả về bất kỳ dữ liệu nào! ý tưởng? – Jascination

+0

Tôi đã thực hiện câu hỏi được cập nhật tại đây: http://stackoverflow.com/questions/18477711/force-angularjs-service-to-return-data-before-loading-controller Tôi sẽ chấp nhận câu trả lời này là câu trả lời hầu hết công việc, nhưng cũng cảm thấy tự do để trả lời công việc đó. – Jascination

0

Sử dụng then thay vì thành công và trì hoãn việc tải của bộ điều khiển con sử dụng ng-include:

<body ng-controller="mainCtrl"> 
    <header>Content</header> 
    <ng-include src="templatePath"></ng-include>   
</body> 

Di chuyển HTML bên trong một mẫu mới userprofile.html:

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

Callback bên trong 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"; 
    }); 
+0

'$ http.success (foo)' là bí danh của '$ http.then (foo)' chuyển tất cả các đối số chính xác.Điều gì sẽ thay đổi 'thành công' thành' sau đó' giải quyết? Xem [nguồn] (https://github.com/angular/angular.js/blob/master/src/ng/http.js#L673). –

+0

@stevuu Yep. Có vẻ như không có điểm nào trong việc sử dụng cái kia. – AlwaysALearner

Các vấn đề liên quan