使用AngularJS 1.2.16,ui-router和Restangular(对于API服务),我有一个具有子状态的抽象状态,它使用多个视图。子视图接受URL参数(通过$ stateParams)以及根据通过URL传递的给定ID从API获取记录的决心。
当您在整个站点中导航时,一切正常,但是如果您在给定页面上并刷新它(Command / Ctrl + r或单击刷新按钮)或通过点击带有ID的深层链接直接加载页面(这是更关键的问题)API服务被请求命中,但承诺永远不会完成解析,因此数据不可用于状态,控制器,模板等。
根据ui-router的文档,在所有承诺都解决之前,不应实例化控制器。我在Google和SO中搜索过高低,阅读了AngularJS,Restangular和ui-router文档,以及大量的博客,并尝试了我知道的每一次迭代来解决这个问题,找不到任何指向解决方案的东西
以下是相关代码:
company.js (控制器代码)
angular.module('my.company', ['ui.router', 'CompanySvc'])
.config(['$stateProvider', function config ($stateProvider) {
$stateProvider
.state('company', {
abstract: true,
url: '/company',
data: {
pageTitle: 'Company'
},
views: {
'main': {
templateUrl: 'company/companyMain.tpl.html'
}
}
})
.state('company.landing', {
url: '/{id}',
views: {
'summary': {
controller: 'CompanyCtrl',
templateUrl: 'company/companyDetails.tpl.html'
},
'locations': {
controller: 'CompanyCtrl',
templateUrl: 'company/companyLocations.tpl.html'
}
},
resolve: {
companySvc: 'CompanySvc',
// Retrieve a company's report, if the id is present
company: ['$log', '$stateParams', 'companySvc', function ($log, $stateParams, companySvc) {
$log.info('In company.landing:resolve and $stateParams is: ', $stateParams);
var id = $stateParams.id;
$log.info('In company.landing:resolve and id is: ', id);
return companySvc.getCompany(id).$promise;
// NOTE SO: this was another stab at getting the promise resolved,
// left commented out for reference
/*return companySvc.getCompany(id).then(function (response) {
return response;
});*/
}]
}
});
}
])
.controller('CompanyCtrl', ['$log', '$scope', '$state', 'company',
function CompanyCtrl ($log, $scope, $state, company) {
$log.info('In CompanyCtrl & $state is: ', $state);
$log.info('In CompanyCtrl and company data is: ', company);
$scope.reportData = company ? company : {};
$log.info('In CompanyCtrl and $scope.reportData is: ', $scope.reportData);
}
]);
companyService.js (使用Restangular的API服务代码)
angular.module('my.companyService', ['restangular']);
.factory('CompanySvc', ['$log', 'Restangular', function ($log, Restangular) {
var restAngular = Restangular.withConfig(function (Configurer) {
Configurer.setBaseUrl('/int');
});
// Object for working with individual Companies
var _companySvc = restAngular.all('companies');
// Expose our CRUD methods
return {
// GET a single record /int/companies/{id}/report
getCompany: function (id) {
$log.info('In CompanySvc.getCompany & id is: ', id);
return restAngular.one('companies', id).customGET('report').then(function success (response) {
$log.info('Retrieved company: ', response);
return response;
}, function error (reason) {
$log.error('ERROR: retrieving company: ', reason);
return false;
});
}
};
}]);
可能添加的其他一些要点: * html5mode使用hashPrefix时为true * app正在由Apache提供重写规则集 * base href已设置 *这是整个应用程序中特有的问题,在这种情况下,数据正在一个状态下被解析;我只是选择了这个例子
最后,这是控制台的一些输出:
In company.landing:resolve and $stateParams is: Object { id="d2c936fb78724880656008a5545b01ea445d4dc4"}
In company.landing:resolve and id is: d2c936fb78724880656008a5545b01ea445d4dc4
In CompanySvc.getCompany & id is: d2c936fb78724880656008a5545b01ea445d4dc4\
In CompanyCtrl & $state is: Object { params={...}, current={...}, $current={...}, more...}
In CompanyCtrl and company data is: undefined
In CompanyCtrl and $scope.reportData is: Object {}
In CompanyCtrl & $state is: Object { params={...}, current={...}, $current={...}, more...}
In CompanyCtrl and company data is: undefined
In CompanyCtrl and $scope.reportData is: Object {}
In CompanyCtrl & $state is: Object { params={...}, current={...}, $current={...}, more...}
Retrieved company: Object { $promise={...}, $resolved=false, route="companies", more...}
答案 0 :(得分:9)
首先只是一个注释。如果你有路由问题(比如那些使用ui-router),而不是使用小提琴,你可以使用像pastebin这样的东西来提供一个可以在本地运行的完整的演示文件,这样就可以测试路由问题。 / p>
我创建了其中一个来自你的小提琴:here
有趣的是,你的模拟演示似乎在路由方面完美无缺。这让我觉得问题出在你的制作服务中。曾经用ui-router
惹恼我的一件事是难以解决resolve
错误,因为似乎几乎没有错误报告。
如果您将此添加到您的应用运行功能(正如我在上面的链接中所做的那样),您应该更好地解决错误输出:
// handle any route related errors (specifically used to check for hidden resolve errors)
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){
console.log(error);
});