最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS $http.get async execution order - Stack Overflow

programmeradmin3浏览0评论

I recently did a lot of coding in AngularJS. After some time it started to feel fortable 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 mands 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 mands 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. .html#5.15.3

I recently did a lot of coding in AngularJS. After some time it started to feel fortable 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 mands 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 mands 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/fhir/2015May/location.html#5.15.3

Share Improve this question asked Jul 9, 2015 at 14:25 J.S.J.S. 651 silver badge6 bronze badges 3
  • They should all start at the same time, however, since it's asynchronous, there's no guarantee in what order they'll plete. – Kevin B Commented Jul 9, 2015 at 14:28
  • Okay, I understand that. But isn't there a way to control the behavior or at least let the function wait? I thought .then() (and it's including promise) synchronises the $http.get!? – J.S. Commented Jul 9, 2015 at 14:47
  • Nope. not possible, unless you want to run them in series, which will be MUCH slower. There are ways though to wait until they're all plete and then handle the responses in the order they were sent. – Kevin B Commented Jul 9, 2015 at 14:48
Add a ment  | 

2 Answers 2

Reset to default 2

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 es 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.

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

发布评论

评论列表(0)

  1. 暂无评论