为什么$ http不会在控制器中加载我的数据 - AngularJS?

时间:2014-12-05 13:32:01

标签: angularjs

我已经建立了一个名为" Data"的工厂。我可以在控制器中使用它,如下所示:

控制器

myApp.controller('MyController', ['$scope', '$firebase', 'Data', function($scope, $firebase, Data) {

// OTHER REFS/FIREBASE

$scope.entries = Data;

}]);

的index.html

<div ng-repeat="entry in entries">
{{entry.name}}
</div>

工厂

myApp.factory('Data', ['$http', function ($http) {

    // load the data
    var entriesz = [];
    $http.get('data/main.json').success(function(data) {
      angular.forEach(data.ParkingFacilities, function(entry) {
         $http.get(entry.staticDataUrl).success(function(data) {
            entriesz.push(angular.extend(entry, data.parkingFacilityInformation));
         });
      });
    });

    //window.alert("Data Imported :" + entriesz.length);
    //window.alert(JSON.stringify(entriesz))

    return entriesz;
    // parse it and store it on firebase

}]);

我现在想知道如何使用此工厂在我的firebase存储中更新它,并创建一个可以访问此存储数据的附加控制器。

P.S。万一你想知道为什么我不使用上面例子中的工厂;基本上,检索数据需要很多计算时间,因此为了节省一些计算时间,我想分割后端和前端进程。

1 个答案:

答案 0 :(得分:2)

很难肯定地说,但似乎你被$http.get的异步性质所困扰。

让我们简化你的代码,对此:

/* 1 */ var entriesz = [];
/* 2 */ $http.get('data/main.json').success(function(data) {
/* 3 */   angular.forEach(data.ParkingFacilities, function(entry) {
/* 4 */      $http.get(entry.staticDataUrl).success(function(data) {
/* 5 */         entriesz.push(angular.extend(entry, data.parkingFacilityInformation));
/* 6 */      });
/* 7 */   });
/* 8 */ });
/* 9 */ window.alert("Data Imported :" + entriesz.length);

我已对行进行编号,以便我们可以更轻松地引用它们。

您似乎期望此代码线性执行,因此第1行,第2行,第3行...第9行。但事实并非如此。每个$http.get调用都开始从远程服务器下载数据。由于这可能需要一段时间,浏览器不会等待数据返回。它只是继续执行其余的代码。然后,当服务器的响应返回时,它会执行您传递到success的回调函数。

所以代码的执行顺序越可能是:1,2,9 ...等待main.json ... 3,4 ......等待数据.... 5,3,4。 ..等待数据... 5,等等。了解这一点,你可能会看到为什么entriesz.length在第9行显示为0:当你发出警报时,条目还没有被加载。

如果您将这些匿名函数从流中取出并给它们这样的名称,则更容易看到:

var entriesz = [];
$http.get('data/main.json').success(onMainJsonLoaded);
window.alert("Data Imported :" + entriesz.length);

function onMainJsonLoaded(data) {
  angular.forEach(data.ParkingFacilities, function(entry) {
     $http.get(entry.staticDataUrl).success(onStaticDataLoaded);
  }
}

function onStaticDataLoaded(data) {
  entriesz.push(angular.extend(entry, data.parkingFacilityInformation));
  window.alert("Partial data imported :" + entriesz.length);
}

这种异步加载是现代网络的一个完全正常的部分,但对那些刚接触它的人来说非常反直觉。试图规避它可能是你天生的本能,但我恳请你不要尝试,而只是接受它。你不能让网络同步(如果可能,也不会有人对此感到高兴),所以你最好的办法是学会处理它的异步性质。

在这种情况下,您可以通过在数据可用时更新UI来实现。例如:我在上面的onStaticDataLoaded函数中添加了一个提醒,以显示当时部分数据已可用。这将是更新网页中“加载{{x}}项目”指标的最佳时机。


我尝试在上述问题的上下文中解释问题。但是已经有很多(可能更好的)类似问题的答案。其中一些可能值得你花时间,所以我会列出它们: