AngularJS $ http.get异步执行顺序

时间:2015-07-09 14:25:33

标签: javascript json angularjs angularjs-http hl7-fhir

我最近在AngularJS中做了很多编码。经过一段时间后,它开始感觉很舒服并且也非常高效。但不幸的是,有一件事我不明白:

在我的项目中,我需要通过$ http.get和RESTful API服务器获取数据。这是我开始绊倒的地方。在处理继续处理数据的函数实现promise($ q.defer等和.then)之后,我认为我已经克服了这个问题。

但是在这段代码中:

$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
};

我无法理解命令的执行顺序。由于我使用了Webstorm IDE及其调试功能,因此我更不准确地说我不知道​​为什么命令按照我不理解的顺序执行。

简单地思考,forEach中包含的所有内容都必须在返回之前执行,因为$ http.get是通过.then连接的。但是在调试信息之后,函数会迭代locationCount ++,甚至在它变深之前返回promise(意味着在第一个.then()之后)。

那是什么意思?我是否误解了AngularJS概念的这一部分?

或者这只是非常糟糕的做法,我应该寻求一个不同的解决方案?

如果上下文很重要/有趣:对象基于https://www.hl7.org/fhir/2015May/location.html#5.15.3

2 个答案:

答案 0 :(得分:2)

使用JavaScript,您只能创建单线程应用程序,例如here他们说不能保证这样。

但我们谈论的是现实世界和真实的浏览器,因此您的代码示例作为单个线程运行(通过相同的线程也用于渲染CSS和HTML,至少在Firefox中)。

涉及异步调用

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

它说“嘿,我以后可以这样做”。它等待它,因为它必须继续当前的线程。

然后,当用return完成当前任务后,它最终可以开始获取远程数据。

证明?检查此fiddle

console.log(1);

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

console.log(3);

你看到for循环的峰值?这是它注册setTimeout异步调用的时刻。在2之前打印仍然是3,因为在打印3之前不会完成任务。

答案 1 :(得分:1)

$ http.get是异步的,因此取决于(除其他事项外)获取的数据有多大,完成&#39; get是可变的。因此,为什么没有说他们将以什么顺序完成