我有一个服务功能,每次访问或刷新路由时都需要调用它。该函数返回Angular承诺。每次调用函数时,promise的结果都需要加载到控制器的作用域中。
我目前正在使用状态定义的resolve参数来调用该函数。
.state('app.theState', {
url: '/theRoute/:theRouteId',
views: {
'menuContent': {
templateUrl: 'templates/theRoute.html',
controller: 'TheRouteCtrl'
}
},
resolve: {theResolvedResult: function(theService){
return theService.theAsyncCall().then(function(result){
return result;
},function(errMsg){
return errMsg;
});}
})
数据作为参数传递给控制器。
.controller( 'TheRouteCtrl', function($scope, $state, $log, theResolvedResult)
我正在更新持有theResolvedResult的全局监视中的控制器$ scope。 (使用此workaround末尾所述的post)。我试着看一下这个论点本身,但它永远不会被触发。
$scope.$state=$state;
$scope.$watch('$state.$current.locals.globals.theResolvedResult', function (result) {
$scope.aValue = result.aValue;
});
不幸的是,我猜因为手表是全局的,当任何路径运行时会触发手表,并且除了定义了解析的路径之外的所有其他路由都会抛出错误。
ionic.bundle.js:26794 TypeError: Cannot read property 'aValue' of undefined
at route_ctrl.js:234
如何修复这些错误,还是有更好的方法来实现这一目标?
答案 0 :(得分:1)
也许只是防范result
未定义的情况:
$scope.$watch('$state.$current.locals.globals.theResolvedResult', function (result) {
if (result) {
$scope.aValue = result.aValue;
}
});
答案 1 :(得分:0)
$onInit
函数/* REPLACE
$scope.$state=$state;
$scope.$watch('$state.$current.locals.globals.theResolvedResult', function (result) {
$scope.aValue = result.aValue;
});
*/
//WITH
this.$onInit = function() {
$scope.aValue = $state.$current.locals.globals.theResolvedResult.aValue;
};
依赖于存在的绑定的初始化逻辑应放在控制器的
$onInit()
方法中,保证在分配绑定后始终调用该方法。— AngularJS Migration Guide (V1.6 $compile breaking change bcd0d4)
决心将被拒绝的承诺转换为履行承诺:
/* ERRONEOUS
resolve: {theResolvedResult: function(theService){
return theService.theAsyncCall().then(function(result){
return result;
},function(errMsg){
//ERRONEOUS converts rejection
return errMsg;
});}
*/
// BETTER
resolve: {
theResolvedResult: function(theService){
return theService.theAsyncCall().then(function(result){
console.log(result);
return result;
},function catchHandler(errMsg){
console.log(errMsg);
//return errMsg;
//IMPORTANT re-throw error
throw errMsg;
});
}
在catch处理程序中重新抛出错误很重要。否则,$q service会将被拒绝的承诺转换为已履行的承诺。这类似于try...catch statement在vanilla JavaScript中的工作方式。
$watch method将函数作为其第一个参数:
/* HACKY
$scope.$state=$state;
$scope.$watch('$state.$current.locals.globals.theResolvedResult', function (result) {
$scope.aValue = result.aValue;
});
*/
//BETTER
//$scope.$state=$state;
//$scope.$watch('$state.$current.locals.globals.theResolvedResult',
$scope.$watch(
function () {
return $state.$current.locals.globals.theResolvedResult;
},
function (result) {
if (result) {
$scope.aValue = result.aValue;
};
});
当$watch method的第一个参数是一个字符串时,它使用$scope
作为其上下文将其评估为Angular Expression。由于$state
服务不是$scope
的属性,因此应使用函数。
答案 2 :(得分:0)
最好的办法是首先避免$watch
黑客攻击。确保价值良好应该在服务中发生,或者至少在resolve
中发生。
查看this Plunker,了解resolve
应如何运作的演示。
一般的想法是resolve
有一份工作;在我们需要时确保数据准备就绪。 docs有一些关于ui.router
如何处理resolve
分辨率的示例。它们有点受限,但通常表明预期会有“好”的结果。错误处理最终由您自己选择。
享受!