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