Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS $http.get async execution order

I recently did a lot of coding in AngularJS. After some time it started to feel comfortable with it and also got really productive. But unfortunately there is this one thing I don't understand:

Within my project I need to get data through $http.get and a RESTful API server. This is where I started to stumble first. After implementing promise ($q.defer etc and .then) at functions which are processing data that's necessary to continue, I thought I conquered the problem.

But in this code:

$scope.getObservationsByLocations = function() {
        var promise = $q.defer();
        var locationCount = 0;

        angular.forEach($scope.analysisData, function(loc) {   // for each location
            $http.get($scope.api + 'Device?_format=json', {     // get all devices
                params: {
                    location: loc.location.id
                }
            }).then(function (resultDevices) {
                var data = angular.fromJson(resultDevices);
                promise.resolve(data);
                // for each device in this location
                angular.forEach(angular.fromJson(resultDevices).data.entry.map(function (dev) {
                    http.get($scope.api + 'Observation?_format=json', {     // get all observations
                        params: {
                            device: dev.resource.id
                        }
                    }).then(function (resultObservations) {
                        var observations = angular.fromJson(resultObservations);
                        // for each obervation of that device in this location
                        angular.forEach(observations.data.entry.map(function(obs) {
                            $scope.analysisData[locationCount].observations.push({observation: obs.resource});
                        }));

                    })
                }))
            });
            locationCount++
        });
        return promise.promise
};

I can't understand in which order the commands are executed. Since I use the Webstorm IDE and it's debugging feature, it would be more accurate to say I don't know why the commands are executed in an order I don't understand.

Thinking simple, everything included in the forEach have to be executed before the return is reached, because $http.get's are connected through .then's. But following the debugging information, the function iterates over locationCount++ and even returns the promise before it goes deeper (meaning after the first .then() ).

What's that all about? Did I misunderstood this part of the AngularJS concept?

Or is this just really bad practice and I should reach out for a different solution?

If the context is important/interesting: Objects are based on i.e. https://www.hl7.org/fhir/2015May/location.html#5.15.3

like image 790
J.S. Avatar asked Jul 09 '15 14:07

J.S.


2 Answers

With JavaScript you can create only single thread applications, although e.g. here they say it is not guaranteed to be like that.

But we are talking about the real world and real browsers, so your code sample is running as a single thread (by the way the same thread is also used for rendering your CSS and HTML, at least in Firefox).

When it comes to an asynchronous call

$http.get($scope.api + 'Device?_format=json', { 

it says "hey, I can do that later". And it waits with that because it must go on with the current thread.

Then, once the current task is done with return it finally can start getting the remote data.

Proof? Check this fiddle:

console.log(1);

for (var i=0;i<1000000;i++) setTimeout(function(){
    console.log(2);
},0);

console.log(3);

You see the spike with the for loop? This is the moment when it registers the setTimeout asynchronous calls. Still 3 is printed before 2 because the task is not done until the 3 is printed.

like image 102
smnbbrv Avatar answered Oct 05 '22 00:10

smnbbrv


The $http.get is asynchronous, so depending on (among other things) how large the fetched data is, the time it takes to 'complete' the get is variable. Hence why there is no saying in what order they will be completed

like image 30
Guinn Avatar answered Oct 05 '22 00:10

Guinn