How to prevent AngularJS from displaying the view until the Ajax request has been completed (页面延迟问题)
$routeProvider resolve propertyallows delaying of route change until data is loaded.
原来在controller中直接ajax直接获取数据:
$http.get(dataUrl)
.success(function(data){ //直接获取数据库,会有延迟,在route 配置中 控制 数据resolve,在将数据传入页面$scope
$scope.data.products=data;
//console.log($scope.data.products);
}).error(function (error) {
$scope.data.error = error;
});
现在 把 取数据 放在resolve 中,再将已经获取的数据传入controller中,即:
app.config(['$routeProvider', function($routeProvider) {
//$locationProvider.html5Mode(true);
$routeProvider
.when("/products", {
templateUrl: "views/productList.html",
controller:'productsShowDelay',
resolve:{
products: ["ProductsLoader", function(ProductsLoader) {
return ProductsLoader();//因为factory为 return function
}]
}
}).when(..).otherwise(..)
.controller('productsShowDelay',['$scope','products',function($scope,products){
$scope.data.products=products;
}])
service.js中配置:
app.factory("productsResource",['$resource','dataUrl',function($resource,dataUrl){
return $resource(dataUrl);
}])
.factory('ProductsLoader', ['productsResource', '$q',function(productsResource,$q){
return function(){
var delay=$q.defer();
productsResource.query(function(ProductsData){
//console.log(ProductsData);
delay.resolve(ProductsData);
},function(errData){
delay.reject(); // you could optionally pass error data here
});
return delay.promise;
};
}]);
下为 overstack 相同问题的解决方法:
$routeProvider resolve property allows delaying of route change until data is loaded.
First define a route with resolve
attribute like this.
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: PhoneListCtrl,
resolve: PhoneListCtrl.resolve}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: PhoneDetailCtrl,
resolve: PhoneDetailCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
notice that the
resolve
property is defined on route.
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone, $q) {
var deferred = $q.defer();
Phone.query(function(successData) {
deferred.resolve(successData);
}, function(errorData) {
deferred.reject(); // you could optionally pass error data here
});
return deferred.promise;
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
Notice that the controller definition contains a resolve object which declares things which should be available to the controller constructor. Here the phones
is injected into the controller and it is defined in the resolve
property.
The resolve.phones
function is responsible for returning a promise. All of the promises are collected and the route change is delayed until after all of the promises are resolved.
上文中 $defer为 angular 1.0.0中 服务,后续版本用 $timeout服务 代替了$defer,
$timeout(function(){
deferred.resolve(ProductsData);
},2000)