我最近在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
答案 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是可变的。因此,为什么没有说他们将以什么顺序完成