AngularJS : controller scope won't sync with promise

标签 angularjs angularjs-scope angularjs-service angularjs-controller angularjs-http

我选择了一个项目,我正在尝试将一些数据从服务返回给我的 Controller 。我已经在这工作了大约 12 个小时,并尝试了不同的方法。它们通常都会导致相同类型的“缺失数据”。

我试过了

  • 使用 $resource 而不是 $http
  • $http.get直接在 Controller 内部而不使用 promise
  • 服务作为实际服务(而不是工厂),不退货
  • 建立工厂以多种不同的方式返回各种格式的数据
  • 使用 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

    这些链接是从今天开始的。

    我认为可能存在 $scope 问题,因为在过去我看到 $scopes 在使用多个 Controller 时无法获取数据,但是该站点只是在 中声明了一个 Controller 。 index.html <body ng-app="myApp" ng-controller="BodyCtrl">设置。主 app.js 使用状态(我相信来自 ui-router)像这样......
    .state('app.view', {
        url: '/view',
        templateUrl: 'views/view.tpl.html',
        controller: 'MyCtrl'
       })
    

    将 Controller 附加到不同的页面。此外,该站点还有一些其他 Controller 从服务中获取数据,我首先将其作为模板查看,但是,那里的数据和返回比我想要的要复杂得多。但最重要的是, Controller 正在访问服务提供的数据。他们都在使用 $resource,这就是我开始处理这个问题的方式。我一直坚持使用 $http 是因为它应该可以工作,并且我希望在我进入“更高级别”之前先使用它。另外,我只需要从端点获取,所以觉得 $resource 有点矫枉过正。

    服务
    .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
    .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
        }
    

    控制台日志

    这是我的控制台日志,我可以通过 获得这么多 ,只是不是实际数据!这就是我需要的。我什至发疯并延长了我的.then(function (data) {捕获 Controller 中需要的所有功能 $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]
    

    据我所知,这应该可行,但我不确定问题可能出在哪里!也许我不明白 promise 是如何工作或解决的。我之前在另一个项目中使用过 Angular,但我在它开始时就在那里并了解它是如何组合在一起的。这个项目的结构不同,感觉更加困惑。我想简化它,但我什至无法返回一些简单的数据!

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

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

    在 Controller 的更深处我有这个
    angular.forEach($scope.data, function (item) {
    // stuff
    }
    

    它似乎无法访问数据。

    EDIT2:我添加了 $http.get我在 Controller 内部使用,以及它的控制台日志和我需要的实际 forEach $scope.data为了

    编辑3:

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

    更新 Controller
    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需要在 View (nvd3 图表)中使用,并且没有获取数据。

    解决方案
    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
            }
        ];
        });
    

    最佳答案

    这可能是一个非常简单的示例,说明您的服务的外观:

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

    在 Controller 中,您可以像这样使用它:
    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 的问题:这仅仅是因为日志发生在异步调用完成之前。

    关于AngularJS : controller scope won't sync with promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23520701/

    相关文章:

    javascript - $scope.param 无法被函数识别

    javascript - Angular.js - 向指令发出周期性事件

    angularjs - 从 angularjs 中的服务调用 Controller 函数

    unit-testing - AngularJS 在服务测试中注入(inject)服务模拟

    css - IE11 问题 : styles used as angularJS variable doesn't render

    javascript - 如何仅针对 angularJS ng-show 和 ng-hide 单击的表行

    javascript - 如何访问 angularjs Controller 中的变量?

    javascript - AngularJS "value"服务可以保存正则表达式吗?

    javascript - 将文件路径作为参数传递到 Angular 路由器中

    javascript - 名称为 'PokemonCtrl' 的 Controller 未注册