Angular服务返回空对象

时间:2015-06-29 10:16:33

标签: angularjs

我一直在尝试用角度制作一个漂亮且用户友好的应用程序,我正在让用户知道在我发出ajax请求时正在加载的部分。我想要完成的任务:我想创建一个处理初始化数据获取的服务,并在数据可用时将数据作为对象传递给控制器​​。当然,在我的控制器需要的所有初始数据可用之前,视图不会显示。这是我到目前为止所拥有的:

app.js

var Application = angular.module('ReporterApplication', ['ngRoute']);

Application.service('Initialize', ['$http', '$q', '$timeout', function($http, $q, $timeout)
{   

    this.serverData = function() 
    {
        $http.get('/packing/scan.action')
            .success(function(data)
            {                         
                return data;
            })
            .error(function(data)
            {
                return data;
            });

    };   

}])


Application.config(['$routeProvider', '$interpolateProvider',

    function($routeProvider, $interpolateProvider) {

        $interpolateProvider.startSymbol('<%');
        $interpolateProvider.endSymbol('%>');

        $routeProvider

            .when('/packing/scan.html', {
                templateUrl: 'packing/scan.html',
                controller: 'PackingScanController as packer',
                resolve: {

                    initData : 'Initialize'   .... etc more code

scan.js

Application.controller('PackingScanController', ['$scope', '$http', 'initData', function($scope, $http, initData) {

    var packer = this;

    packer.packedToday = initData.serverData(); ... etc more code

3 个答案:

答案 0 :(得分:1)

如果您希望控制器等待,您需要做的是正确配置resolve选项。为此,您需要让您的服务返回一个承诺,否则路由器将不会等待。

  

resolve - {Object.<string, function>=} - 应该注入控制器的可选依赖关系图。 如果这些依赖项中的任何一个是承诺,路由器将等待它们全部被解析或者在实例化控制器之前被拒绝。

这是一个简单的例子:

app.service('Initialize', ['$http', function($http) {
  this.serverData = function()
  {
    // return the http promise
    return $http
      .get('config.json')
      // use success/error if needed
      .then(function (response) {
        // make sure, only the response data is used
        return response.data;
      })
    ;
  };
}]);

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/', {
      template: '<pre>{{ main.initData|json }}</pre>',
      controller: 'MainCtrl as main',
      resolve: {
        // configure with DI
        initData: ['Initialize', function (Initialize) {
          // call the service method, and return the promise
          return Initialize.serverData();
        }]
      }
    })
  ;
}]);

app.controller('MainCtrl', function (initData) {
  // initData will be loaded
  this.initData = initData;
});

演示http://plnkr.co/edit/sOwyHz4yMvwujBWYzOn0?p=preview

答案 1 :(得分:0)

您可以在任何控制器中注入您的服务,这样您就不需要通过解决方案传递它。

Application.controller('PackingScanController', ['$scope', '$http', 'Initialize', function($scope, $http, Initialize)

对于装载机,通常我所做的是使用ng-show

检查模板中数据的可用性
<div ng-show="!data">Loading...</div>
<div ng-show="!!data" ng-repeat="d in data">...</div>

每当您需要显示加载程序时,只需将您的$ scope.data设置为null并继续调用您的API服务。

顺便提一下,如果您的评论中没有其他用户建议,您的服务将无法正常运行。

答案 2 :(得分:0)

  

所有这些错误都来自于我们正在尝试将异步调用转换为同步调用。这根本不可能。

     

serverData()不再返回任何内容。返回数据   语句未从serverData()返回。它从...返回   匿名回调函数传递给then()。

     

不会立即调用匿名回调。它叫做什么时候   响应是可用的。这种情况发生在serverData()之后很久   返回。

所以, 的 1。单向:使用回调

Application.service('initdata',function($http){
    var serverData = function(callback){
        $http.get('/packing/scan.action').then(function(response){
            callback(response.data);
        });
   };

   return {
       serverData: serverData
   };
});

Application.controller('PackingScanController',function(initdata){
    initdata.serverData(function(serverdata){
       $scope.serverdata = serverdata;
    });
});

<强> 2。第二种方式只需返回HTTP承诺,让控制器处理它。

Application.service('initdata',function($http){
    var serverData = function(){
        return $http.get('/packing/scan.action');
    };

    return {
        serverData: serverData
    };  
});

Application.controller('PackingScanController',function(initdata){
    initdata.serverData().then(function(response){
        $scope.serverdata = response.data;
    });
});

3.您还可以返回serverData promise,而不是返回http响应承诺。

Application.service('initdata',function($http){
    var serverData = function() {
        var defer = $q.defer();

        $http.get('/api/ponies').then(function(response) {
            defer.resolve(response.data);
        });

        return defer.promise;
    };

    return {
        serverData: serverData
    };  
});

Application.controller('PackingScanController',function(initdata){
    initdata.serverData().then(function(response){
        $scope.serverdata = response.data;
    });
});