6

我已经拿起一个项目,我试图从服务返回一些数据到我的控制器。我一直在这里约12小时,并尝试了不同的方法。它们通常都会导致同样的“缺失数据”。AngularJS:控制器范围将不会与承诺同步

我使用$资源,而不是试图

  • $ HTTP
  • $http.get右控制器内部没有使用的承诺
  • 服务作为实际服务(而不是工厂),而不返回
  • 构建工厂一堆不同的方式返回各种格式的数据
  • 使用setTimeout和$ apply

我觉得我现在已经是一个简单的,因为我可以得到它,一切我读过说这应该工作

angularjs-load-data-from-service

angular-controller-cant-get-data-from-service

angularjs-promises-not-firing-when-returned-from-a-service

angularjs-promise-not-resolving-properly

angularjs-promise

这些链接只是从今天起。

我认为有可能是一个$范围的问题,因为在过去我见过$范围时,多个控制器习惯没有得到数据,但是该网站仅仅声明中的index.html控制器为<body ng-app="myApp" ng-controller="BodyCtrl">设置。主要app.js使用状态(从UI路由器我相信)是这样的...

.state('app.view', { 
    url: '/view', 
    templateUrl: 'views/view.tpl.html', 
    controller: 'MyCtrl' 
    }) 

到控制器连接到不同的页面。此外,该网站还有一些其他控制器从服务器获取数据,我首先将其作为模板进行了查看,但是,数据和回报比我想要的要复杂得多。尽管如此,控制器正在访问从服务提供的数据。他们都使用$资源,这是我从这个问题开始的。我一直坚持使用$ http,因为它应该的工作,并且我想在我进入更高级别之前使用它。另外,我只需要从端点获得GET,所以感觉$资源是过量的。

服务

.factory('MyService', ['$http', '$q', '$rootScope', function ($http, $q, $rootScope) { 
    var defer = $q.defer(); 
    var factory = {}; 
    factory.all = function() { 
     $http({method: 'GET', url: 'http://URLtoJSONEndpoint'}). 
      success(function (data, status, headers, config) { 
       console.log('data success', data); 
       defer.resolve(data); 
      }). 
      error(function (data, status, headers, config) { 
       console.log('data error'); 
       defer.reject(data); 
      }); 

     return defer.promise; 
    }; 
    return factory; 
}]); 

控制器

.controller('MyCtrl', ['$scope', '$state', '$stateParams', '$rootScope', 'MyService', '$q', function ($scope, $state, $stateParams, $rootScope, MyService, $q) { 
... 
... 
$scope.data = null; 
$scope.object = MyService; 
$scope.promise = MyService.all(); 

MyService.all().then(function (data) { 
    $scope.data = data; 
    console.log("data in promise", $scope.data); 
}) 
console.log("data", $scope.data); 
console.log("object", $scope.object); 
console.log("promise", $scope.promise); 

$http({method: 'GET', url: 'http://URL'}). 
     success(function (data, status, headers, config) { 
      $scope.data = data; 
      console.log('data success in ctrl', data); 
     }). 
     error(function (data, status, headers, config) { 
      console.log('data error'); 
     }); 

    console.log("data after ctrl", $scope.data); 


    angular.forEach($scope.data, function (item) { 
     // stuff that I need $scope.data for 
    } 

控制台日志

所以这是我的控制台日志,我可以在所以睦得到h,只是不是实际的数据!这是我需要的。我甚至疯了,并延长我的.then(function (data) {捕获控制器中需要$scope.data的所有功能。那是一列火车残骸。

***data null*** 
object Object {all: function} 
promise Object {then: function, catch: function, finally: function} 
***data success after ctrl null*** 
data success in ctrl Array[143] 
data success Array[143] 
data in promise Array[143] 
data success Array[143] 

据我所知,这应该工作,但我不知道还有什么地方的问题都可以!也许我不明白承诺如何工作或解决。我之前在另一个项目中使用过Angular,但我在开始时就已经了解它,并了解它是如何组合在一起的。这个项目的结构不同,感觉更加混乱。我想简化它,但我甚至无法得到一些简单的数据返回!

我很感激任何帮助/反馈,您可以提供确定为什么这不起作用,谢谢!

编辑:所以问题是,为什么console.log("data", $scope.data)回到空/承诺之前?

有点控制器后面我有这个

angular.forEach($scope.data, function (item) { 
// stuff 
} 

,它似乎并没有能够访问的数据。

EDIT2:我已经添加了我所用的控制器内的$http.get,与它和真正的forEach控制台日志沿着我需要$scope.data

EDIT3:

更新服务

.service('MyService', ['$http', function ($http) { 
    function all() { 
     return $http({ 
      url: 'http://URL', 
      method: 'GET' 
     }); 
    } 

    return { 
     all: all 
    } 
}]); 

更新控制器

MyService.all().success(function (data) { 
     $scope.data = data; 

     angular.forEach($scope.data, function (item) { 

      // Turn date value into timestamp, which is needed by NVD3 for mapping dates 
      var visitDate = new Date(item.testDate).getTime(); 

      switch (item.Class) { 
       case "TEST": 
        testData.push(
         [ 
          visitDate, 
          item.Total 
         ] 
        ); 

      } 

     }); 

     console.log("test Data in success", testData); 
    }); 


$scope.testData = [ 
     { 
      "key": "Test", 
      "values": testData 
     } 
    ]; 

所以$scope.testData需要在视图(nvd3图表)中使用,它不会获取数据。

SOLUTION

MyService.all().success(function (data) { 
     $scope.data = data; 

     angular.forEach($scope.data, function (item) { 

      // Turn date value into timestamp, which is needed by NVD3 for mapping dates 
      var visitDate = new Date(item.testDate).getTime(); 

      switch (item.Class) { 
       case "TEST": 
        testData.push(
         [ 
          visitDate, 
          item.Total 
         ] 
        ); 
      } 

     }); 

     console.log("test Data in success", testData); 

     $scope.testData = [ 
     { 
      "key": "Test", 
      "values": testData 
     } 
    ]; 
    }); 
+2

所以你的问题是,为什么'的console.log(“数据”,$ scope.data); // =>数据null'?如果是,那么可能是因为在异步调用完成之前执行日志。Sidenote对'MyService.all();'的两次调用实际上会触发两个请求。我认为第一个没有必要。 – Yoshi

+1

是的,确切!感谢您指出这一点,不是很清楚 – mykepwnage

+1

我会开始通过让它在你的控制器内工作,所以成功做$ scope.data = data;当您可以看到呼叫成功工作时,开始使用服务重新定位,认为您正在增加复杂性。 $ http已经返回一个承诺,所以你不需要使用另一个承诺。 https://docs.angularjs.org/api/ng/service/$http – LightningShield

回答

5

这可能是您的服务如何能看起来像一个非常简单的例子:

app.service('MyService', ['$http', function ($http) { 
    function all() { 
    return $http({ 
     url: 'data.json', 
     method: 'GET' 
    }); 
    } 

    return { 
    all: all 
    } 
}]); 

在控制器中使用它,像这样:

app.controller('AppCtrl', ['$scope', 'MyService', function ($scope, MyService) { 
    $scope.data = null; 

    MyService.all().success(function (data) { 
    $scope.data = data; 

    // init further handling of `.data` here. 
    }); 
}]); 

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


要回答这个问题,为什么控制台日志data null:这很简单,因为日志的异步调用完成之前发生。

0

我正面临同样的问题。我解决这个问题,通过使用$rootScope承诺内,而不是$scope.So$rootScope.data将缴费在console.log