It is hard to say with certainty, but it seems like you are being bitten by the asynchronous nature of $http.get
.
Let's simplify your code a bit, to this:
/* 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);
I've numbered the lines so we can refer to them more easily.
You seem to expect that this code executes linearly, so line 1, line 2, line 3... line 9. But that is not what happens. Each of those $http.get
calls starts downloading data from a remote server. And since that may take quite some time, the browser doesn't wait for the data to come back. It simply continues to execute the rest of the code. Then when the response from the server comes back, it executes the callback function that you passed into success
.
So the more likely execution order of your code is: 1, 2, 9... waiting for main.json... 3, 4... waiting for the data.... 5, 3, 4... waiting for data... 5, etc. Knowing this, you can probably see why entriesz.length
is showing up as 0
in line 9: the entries haven't been loaded yet when you alert.
This is easier to see if you take those anonymous functions out of the flow and give them names like this:
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);
}
This asynchronous loading is a completely normal part of the modern web, but highly counter-intuitive to those new to it. It may be your natural instinct to try and circumvent it, but I urge you to not try that and instead just accept it. You cannot make the web synchronous (nor would anyone be happy about it if you could), so your best bet is to learn to deal with its asynchronous nature.
In this case, you do that by updating your UI as data becomes available. For example: I added an alert to the onStaticDataLoaded
function above, to show that part of your data has become available at that time. This would be the perfect time to update a "{{x}} items are loaded" indicator in your web page.
I tried explaining the problem in the context of your question above. But there are plenty of (probably better) answers to similar questions already. Some of those might be worth your time, so I'll list them: