Cra*_*ank 2 javascript angularjs single-page-application restangular angular-ui-router
使用AngularJS 1.2.16,ui-router和Restangular(对于API服务),我有一个带有子状态的抽象状态,它使用多个视图.子视图接受URL参数(通过$ stateParams)以及根据通过URL传递的给定ID从API获取记录的决心.
当您在整个站点中导航时,一切都很完美,但是如果您在给定页面上并刷新它(Command/Ctrl + r或单击刷新按钮)或通过点击带有ID的深层链接直接加载页面(这是更重要的问题)API服务被请求命中,但承诺永远不会完成解析,因此数据不可用于状态,控制器,模板等.
根据ui-router的文档,在所有promise都解决之前,不应该实例化控制器.我在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);
}
]);
Run Code Online (Sandbox Code Playgroud)
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;
});
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
可能添加的其他一些要点:*html5mode为true,其中一个hashPrefix*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...}
Run Code Online (Sandbox Code Playgroud)
首先只是一个注释.如果你有路由问题(比如那些使用ui-router),而不是使用小提琴,你可以使用像pastebin这样的东西来提供一个可以在本地运行的完整的演示文件,这样就可以测试路由问题.
我从你的小提琴中创造了一个:这里
有趣的是,你的模拟演示似乎在路由方面完美无缺.这让我觉得问题出在你的制作服务中.曾经让我烦恼的一件事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);
});
Run Code Online (Sandbox Code Playgroud)