2012-09-10 9 views
15

Chciałbym opóźnić inicjalizację kontrolera do momentu, aż niezbędne dane nie dotrą z serwera.Angular.js inicjowanie sterownika opóźniającego

Znalazłem rozwiązanie dla Kątowymi 1.0.1: Delaying AngularJS route change until model loaded to prevent flicker, ale nie mógł on pracować z Kątowymi 1.1.0

Szablon

<script type="text/ng-template" id="/editor-tpl.html"> 
Editor Template {{datasets}} 
</script> 
    <div ng-view> 
</div> 

JavaScript

function MyCtrl($scope) {  
    $scope.datasets = "initial value"; 
} 

MyCtrl.resolve = { 
    datasets : function($q, $http, $location) { 
     var deferred = $q.defer(); 

     //use setTimeout instead of $http.get to simulate waiting for reply from server 
     setTimeout(function(){ 
      console.log("whatever"); 
      deferred.resolve("updated value"); 
     }, 2000); 

     return deferred.promise; 
    } 
}; 

var myApp = angular.module('myApp', [], function($routeProvider) { 
    $routeProvider.when('/', { 
     templateUrl: '/editor-tpl.html', 
     controller: MyCtrl, 
     resolve: MyCtrl.resolve 
    }); 
});​ 

http://jsfiddle.net/dTJ9N/1/

Odpowiedz

11

Od $ http zwraca obietnicę, że to hit wydajność tworzenia własnych odroczone tylko do powrotu obietnicę, gdy dane http przybywa. Powinieneś być w stanie to zrobić:

MyCtrl.resolve = { 
    datasets: function ($http) { 
     return $http({method: 'GET', url: '/someUrl'}); 
    } 
}; 

Jeśli trzeba wykonać pewne przetwarzanie rezultaty daje stosowanie .then, a obietnica jest przykuty w za darmo:

MyCtrl.resolve = { 
    datasets: function ($http) { 
     return $http({method: 'GET', url: '/someUrl'}) 
       .then (function (data) { 
        return frob (data); 
       }); 
    } 
}; 
+0

Przykład pracy: http://jsfiddle.net/dTJ9N/5 – mb21

+10

Powiedziałbym, że Uderzenie wydajności za zawijanie obietnicy $ http z inną obietnicą w tym przypadku jest tak małe, że nie warto się tym przejmować. Jednak bardziej zwięzły kod wynikający z wyłączenia dodatkowej obietnicy jest godnym pościgiem. –

+0

Kod jest ładny i czysty, ale na dzień dzisiejszy skrzypce są zepsute, pokazuje źródło dokumentu. Zbyt nowi dla Angulara, aby pomóc, nie wspominając o tym. – enigment

1

Można spojrzeć na niemal identycznym pytaniem here który korzysta z zasobów, ale to działa w ten sam sposób z $ http. Myślę, że to powinno działać

function MyCtrl($scope, datasets) {  
    $scope.datasets = datasets; 
} 

MyCtrl.resolve = { 
    datasets: function($http, $q) { 
     var deferred = $q.defer(); 

     $http({method: 'GET', url: '/someUrl'}) 
      .success(function(data) { 
       deferred.resolve(data) 
     } 

     return deferred.promise; 
    } 
}; 

var myApp = angular.module('myApp', [], function($routeProvider) { 
    $routeProvider.when('/', { 
     templateUrl: '/editor-tpl.html', 
     controller: MyCtrl, 
     resolve: MyCtrl.resolve 
    }); 
});​ 
+0

Dzięki, poprawiono błąd składni lub dwa, tutaj działający kod: http://jsfiddle.net/dTJ9N/2/ – mb21

4

Zawsze możesz po prostu umieścić "ng-show" na najbardziej zewnętrznym elemencie DOM i ustaw go jako równy danym, na które chcesz poczekać.

Na przykład podany na stronie Angular JS domu można zobaczyć, jak łatwo jest: http://plnkr.co/CQu8QB94Ra687IK6KgHn Wszystko, co mieliśmy do zrobienia było ten sposób formularz nie będą wyświetlane, dopóki ta wartość została ustalona.

O wiele bardziej intuicyjny i mniej pracujący w ten sposób.

+0

co, jeśli masz wiele ładowań danych? nie wiesz, który z nich się skończy, ponieważ wszyscy biegną asyn. Na przykład ... załóżmy, że potrzebuję 5 opcji do pokazania w polu wyboru i wszystkich danych dotyczących pierwszej opcji, więc mogę wstępnie załadować formularz ??? – Jason

+0

Jeśli masz pięć, nie ma problemu, po każdym ładowaniu po prostu zanotuj i po wykonaniu wszystkich pięciu będziesz szczęśliwy. Musisz tylko mieć zmienną z tablicą i sprawdzić, czy długość wynosi 5 po dodaniu każdego ładunku danych, a po 5 ustawić inną zmienną, na której opiera się program ng-show i zresetować tablicę zliczania. – stormlifter