【问题标题】:AngularJS route resolve get $http data with idAngularJS 路由解析获取带有 id 的 $http 数据
【发布时间】:2015-04-17 05:24:11
【问题描述】:

我有几个依赖于服务器数据的屏幕和控制器。因此,我想通过路由器解析功能来解决数据依赖关系,以便在渲染屏幕之前确保所有数据都可以通过 Promise 获得。但是,我不确定我是否正确理解了用法,因为以下示例似乎不起作用。为什么?

angular.module('app',['ngRoute'])
    .service('Data1', function ($q, $routeProvider, $http) {
        var self = this;

        this.fetch = function() {return $http.get('/json/data1',{id:$routeProvider.id})}
    }
    .service('Data2', function ($q, $routeProvider, $http) {
        var self = this;
        this.fetch = function() {return $http.get('/json/data2',{id:$routeProvider.id})}
    }
    .config(function($routeProvider){
        §routeProvider.when('/:id',{
            controller:'TestCtrl',
            templateUrl:'template.html',
            resolve: {
                data1: function (Data1) { return Data1.fetch(); },
                data1: function (Data2) { return Data2.fetch(); }
            }

        });
    })
    .controller('TestCtrl', function($location, $routeParams, $http, data1,data2) {
        console.log(data1);
        console.log(data2);
    });

【问题讨论】:

  • 我明白了,您想使用$routeProvider 路由上的resolve 属性从您的服务加载数据,然后将它们注入您的控制器?
  • 没错,这就是我想做的事
  • 或者这是个坏主意?
  • 不,这完全合理。他们专门为此构建了功能。我现在正在为您编写一个示例。

标签: javascript angularjs


【解决方案1】:

这是一个如何正确使用resolve$routeProvider 的示例。首先,我定义了两个工厂,就像你在那里一样,然后在我的配置中我设置了一个我想从我的工厂注入数据的路由。我告诉它我想使用什么控制器,模板在这种情况下是无关紧要的。然后在解析下,我给它一个具有两个属性的对象,即函数someDatasomeMoreData。在这两个函数上,我注入了我的data1data2 工厂和$routeParams,从工厂获取数据,然后返回数据。

在我的控制器定义中,我告诉它我想注入$scope,然后我告诉它我想注入另外两个东西,这些是我在$routeProvider 中定义的解析属性。

需要注意的一点是,如果您在工厂中执行实际的 API 调用并希望从中解析数据,则在解析数据之前页面不会加载,控制器甚至不会启动,直到这些都完成完毕。所以你可能想想出一些方法来制作加载动画,这里有很多关于如何做到这一点的示例。

angular.module('app.factories', [])
  .factory('data1', ['$q', '$timeout', function($q, $timeout) {
    return {
      getData: function(id) {
        var deferred = $q.defer();
        var promise = deferred.promise;
        
        $timeout(function() {
          deferred.resolve('this is factory 1, id: ' + id);
        }, 2000);
        
        return promise;
      }
    };
  }])
  .factory('data2', ['$q', '$timeout', function($q, $timeout) {
    return {
      getData: function(id) {
        var deferred = $q.defer();
        var promise = deferred.promise;
        
        $timeout(function() {
          deferred.resolve('this is factory 2, id: ' + id);
        }, 2000);
        
        return promise;
      }
    };
  }]);

angular.module('app', ['ngRoute', 'app.factories'])
  .config(['$routeProvider',
    function($routeProvider) {
      $routeProvider
        .when('/', {
          controller: 'defaultCtrl',
          template:'<a href="#/1">Go to route with parameter on it</a>'
        })
        .when('/:id', {
          controller: 'testCtrl',
          template: '<span ng-bind="string1"></span><br /><span ng-bind="string2"></span>',
          resolve: {
            someData: ['data1', '$route',
              function(data1, $route) {
                console.log('resolving someData');
                return data1.getData($route.current.params.id).then(
                  function(response) {
                    return response;
                  });
              }
            ],
            someMoreData: ['data2', '$route',
              function(data2, $route) {
                console.log('resolving someMoreData');
                return data2.getData($route.current.params.id).then(
                  function(response) {
                    return response;
                  });
              }
            ]
          }
        });
    }
  ])
  .controller('defaultCtrl', function() { })
  .controller('testCtrl', ['$scope', 'someData', 'someMoreData',
    function($scope, someData, someMoreData) {
      console.log('in route with id param');
      $scope.string1 = someData;
      $scope.string2 = someMoreData;
    }
  ]);
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-route.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
  <div ng-view>

  </div>
</body>

</html>

编辑 修改它,使您的工厂在他们自己的模块中并作为对应用程序模块的依赖项注入,而不是在应用程序模块本身上,恕我直言,它倾向于更好的架构(大多数时候我给每个单独的工厂它自己的模块,但为了简洁起见,我保持简单)

【讨论】:

  • THX Ben,当我读到 resolve 可以处理 $http 的承诺时,我想知道如何使用它们?
  • 我已经编辑了我的答案,展示了一个使用 Promise 的示例,希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
  • 2020-04-04
相关资源
最近更新 更多