javascript - AngularJS $http.get 异步执行顺序

标签 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

最佳答案

使用 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 之前任务未完成。

关于javascript - AngularJS $http.get 异步执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31320401/

相关文章:

angularjs - 基于路由隐藏ng-view DOM之外的元素

javascript - 在函数上使用 .bind() 并将一些参数设置为常量而不是其他参数,JavaScript

javascript - 无法通过 Id 更改 div 的 innerHTML

javascript - 使用 str.replace() 在 JavaScript 字符串中插入 "."

java - 将 Spring 上下文添加到 Jackson 生成的对象

javascript - AngularJS:更改指令属性

javascript - 在 handlebars.js 中使用具有数字属性的对象

java - 如何将 List 包装为 Jackson 生成的 JSON 中的顶级元素

java - 如何使用 Jersey 来编码和解码 map

angularjs - 如何列出模板缓存中的所有内容?