Angular 使用 ui-router 时解决
Angular resolve when using ui-router
我确定这是配置错误,但不确定如何使用 angular 正确绕过它。
我的状态设置是这样的
$stateProvider
.state('app', {
url: '',
abstract: true,
templateProvider: ['$templateCache', function ($templateCache) {
return $templateCache.get('app/main/main.html');
}],
controller: 'MainController',
resolve: {
Pages: ['PageFactory', function (PageFactory) {
return PageFactory.getAll();
}]
}
})
.state('app.home', {
url: '/home',
views: {
'content@app': {
templateProvider: ['$templateCache', function ($templateCache) {
return $templateCache.get('app/page/page.html');
}],
controller: 'PageController'
}
},
resolve: {
Page: ['$stateParams', 'PageFactory', function ($stateParams, PageFactory) {
return PageFactory.get($stateParams.id);
}],
ModuleData: function () {
return {};
},
Form: function () {
return {};
}
}
});
现在我的问题是,如果 PageFactory.get($stateParams.id) 失败,则重新加载页面,然后重新加载和重新加载。
这是来自 PageFactory 的示例,如您所见returns 承诺
angular.module('app').factory('PageFactory', ['$http', '$q', function ($http, $q) {
var urlBase = 'api/page';
var factory = {};
factory.getAll = function () {
var $defer = $q.defer();
$http.get(urlBase)
.success(function (data) {
$defer.resolve(data);
})
.error(function (error) {
$defer.reject(error);
});
return $defer.promise;
};
factory.get = function (id) {
var $defer = $q.defer();
$http.get(urlBase + '/' + id)
.success(function (data) {
$defer.resolve(data);
})
.error(function (error) {
$defer.reject(error);
});
return $defer.promise;
};
}]);
可以限制尝试解决的次数,还是我应该首先进行不同的设置?
我在将站点从一个地方移动到另一个地方时注意到了这一点,并且需要在我的 index.html 页面中指定一个基本 href。因为 $http 试图连接到一个不存在的 url,所以它一直在尝试、尝试、尝试,如果有人离开,它会损害我们的网络服务器性能。
我的状态应用程序是我的路线状态(抽象状态),用户在进入网站后默认为 app.home。我想这就是它不断重试解决的原因?
使用 resolve with promises 的常用方法是使用 $q.defer()
Pages: ['PageFactory', '$q', function (PageFactory, $q) {
var deffered = $q.defer();
PageFactory.getAll()
.success(function(data) {
deffered.resolve(data);
})
.error(function(data) {
deffered.reject();
})
return deferred.promise;
}]
如果失败,这将拒绝状态更改,或者您可以在失败时执行任何操作。如果成功,它会传递数据。
也看到这个post关于同样的事情。
Angular ui-router get asynchronous data with resolve
当解析出现错误时,我们也有无限循环,所以我们最终在 $stateChangeError 事件处理程序中有更多的逻辑。既然有了这个,我们就再也没有循环的麻烦了。
看看我们如何检查我们试图去哪里,如果我们在回到本地状态时失败了,我们不会再试一次,而是重定向到一个简单的错误状态。
这里是我们的例子,这是在我们主模块的 运行 方法中设置的:
$rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
console.log('Error on StateChange from: "' + (fromState && fromState.name) + '" to: "'+ toState.name + '", err:' + error.message + ", code: " + error.status);
if(error.status === 401) { // Unauthorized
$state.go('signin.content');
} else if (error.status === 503) {
// the backend is down for maintenance, we stay on the page
// a message is shown to the user automatically by the error interceptor
event.preventDefault();
} else {
$rootScope.$emit('clientmsg:error', error);
console.log('Stack: ' + error.stack);
// check if we tried to go to a home state, then we cannot redirect again to the same
// homestate, because that would lead to a loop
if (toState.name === 'home') {
return $state.go('error');
} else {
return $state.go('home');
}
}
});
我确定这是配置错误,但不确定如何使用 angular 正确绕过它。
我的状态设置是这样的
$stateProvider
.state('app', {
url: '',
abstract: true,
templateProvider: ['$templateCache', function ($templateCache) {
return $templateCache.get('app/main/main.html');
}],
controller: 'MainController',
resolve: {
Pages: ['PageFactory', function (PageFactory) {
return PageFactory.getAll();
}]
}
})
.state('app.home', {
url: '/home',
views: {
'content@app': {
templateProvider: ['$templateCache', function ($templateCache) {
return $templateCache.get('app/page/page.html');
}],
controller: 'PageController'
}
},
resolve: {
Page: ['$stateParams', 'PageFactory', function ($stateParams, PageFactory) {
return PageFactory.get($stateParams.id);
}],
ModuleData: function () {
return {};
},
Form: function () {
return {};
}
}
});
现在我的问题是,如果 PageFactory.get($stateParams.id) 失败,则重新加载页面,然后重新加载和重新加载。
这是来自 PageFactory 的示例,如您所见returns 承诺
angular.module('app').factory('PageFactory', ['$http', '$q', function ($http, $q) {
var urlBase = 'api/page';
var factory = {};
factory.getAll = function () {
var $defer = $q.defer();
$http.get(urlBase)
.success(function (data) {
$defer.resolve(data);
})
.error(function (error) {
$defer.reject(error);
});
return $defer.promise;
};
factory.get = function (id) {
var $defer = $q.defer();
$http.get(urlBase + '/' + id)
.success(function (data) {
$defer.resolve(data);
})
.error(function (error) {
$defer.reject(error);
});
return $defer.promise;
};
}]);
可以限制尝试解决的次数,还是我应该首先进行不同的设置?
我在将站点从一个地方移动到另一个地方时注意到了这一点,并且需要在我的 index.html 页面中指定一个基本 href。因为 $http 试图连接到一个不存在的 url,所以它一直在尝试、尝试、尝试,如果有人离开,它会损害我们的网络服务器性能。
我的状态应用程序是我的路线状态(抽象状态),用户在进入网站后默认为 app.home。我想这就是它不断重试解决的原因?
使用 resolve with promises 的常用方法是使用 $q.defer()
Pages: ['PageFactory', '$q', function (PageFactory, $q) {
var deffered = $q.defer();
PageFactory.getAll()
.success(function(data) {
deffered.resolve(data);
})
.error(function(data) {
deffered.reject();
})
return deferred.promise;
}]
如果失败,这将拒绝状态更改,或者您可以在失败时执行任何操作。如果成功,它会传递数据。
也看到这个post关于同样的事情。
Angular ui-router get asynchronous data with resolve
当解析出现错误时,我们也有无限循环,所以我们最终在 $stateChangeError 事件处理程序中有更多的逻辑。既然有了这个,我们就再也没有循环的麻烦了。
看看我们如何检查我们试图去哪里,如果我们在回到本地状态时失败了,我们不会再试一次,而是重定向到一个简单的错误状态。
这里是我们的例子,这是在我们主模块的 运行 方法中设置的:
$rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
console.log('Error on StateChange from: "' + (fromState && fromState.name) + '" to: "'+ toState.name + '", err:' + error.message + ", code: " + error.status);
if(error.status === 401) { // Unauthorized
$state.go('signin.content');
} else if (error.status === 503) {
// the backend is down for maintenance, we stay on the page
// a message is shown to the user automatically by the error interceptor
event.preventDefault();
} else {
$rootScope.$emit('clientmsg:error', error);
console.log('Stack: ' + error.stack);
// check if we tried to go to a home state, then we cannot redirect again to the same
// homestate, because that would lead to a loop
if (toState.name === 'home') {
return $state.go('error');
} else {
return $state.go('home');
}
}
});