AngularJS路由解析获取带有id的$ http数据

时间:2015-04-16 15:13:48

标签: javascript angularjs

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

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);
    });

1 个答案:

答案 0 :(得分:1)

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

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

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

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>

修改 修改它,以便你的工厂在他们自己的模块中,并作为依赖注入app模块,而不是在app模块本身,这是恕我直言倾向于更好的架构(大多数时候我给每个工厂它自己的模块,但为了简洁起见,我保持简单)