0

我有一个服务功能,每次访问或刷新路线时都需要调用它。该函数返回一个 Angular 承诺。每次调用函数时,都需要将 promise 的结果加载到控制器的作用域中。

我目前正在状态定义上使用解析参数来调用该函数。

.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)

我正在更新控制器 $scope 在全局的监视中,它保存了 ResolvedResult。(使用本文末尾描述解决方法)。我尝试观察论点本身,但它从未被触发。

$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

我该如何解决这些错误,或者有更好的方法吗?

4

3 回答 3

1

也许只是防止result未定义的情况:

$scope.$watch('$state.$current.locals.globals.theResolvedResult', function (result) {
  if (result) {
    $scope.aValue = result.aValue;
  }
});
于 2017-04-28T00:07:42.530 回答
0

Angular V1.6 的重大更改

将初始化逻辑移到$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 迁移指南(V1.6 $compile 重大更改 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 服务会将被拒绝的承诺转换为已履行的承诺。这类似于try...catch 语句在 vanilla JavaScript 中的工作方式。

$watch 方法接受一个函数作为它的第一个参数:

/* 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 方法的第一个参数是一个字符串时,它会将其评估为一个Angular 表达式,并使用$scope它的上下文。由于$state服务不是$scope函数的属性,因此应改为使用。

于 2017-04-28T04:29:39.280 回答
0

最好的选择是首先避免$watch黑客攻击。确保价值是好的应该发生在服务中,或者至少在resolve.

查看这个 Plunkerresolve以了解如何工作的演示。

一般的想法是resolve有一份工作;确保数据在我们需要时准备就绪。该文档有一些关于如何ui.router处理resolve分辨率的示例。它们有点有限,但通常表明“好”的结果是可以预期的。错误处理最终取决于您自己的选择。

享受!

于 2017-07-10T08:06:14.573 回答