AngularJS $http.get 异步执行顺序
AngularJS $http.get async execution order
我最近在 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 中包含的所有内容都必须在到达 return 之前执行,因为 $http.get 是通过 .then 连接的。但是根据调试信息,该函数会遍历 locationCount++ 甚至 return 在它深入之前(意味着在第一个 .then() 之后)的承诺。
这是怎么回事?我是否误解了 AngularJS 概念的这一部分?
或者这真的是一种糟糕的做法,我应该寻求不同的解决方案吗?
如果上下文是 important/interesting:对象基于 https://www.hl7.org/fhir/2015May/location.html#5.15.3
$http.get 是异步的,因此根据(除其他事项外)获取的数据有多大,'complete' 获取所需的时间是可变的。因此,为什么没有说明它们将按什么顺序完成
使用 JavaScript 您只能创建单线程应用程序,尽管例如here他们说不能保证是那样。
但我们谈论的是真实世界和真实浏览器,因此您的代码示例 运行 作为单个线程(顺便说一下,同一线程也用于呈现您的 CSS 和HTML,至少在 Firefox 中是这样。
说到异步调用
$http.get($scope.api + 'Device?_format=json', {
它说 "hey, I can do that later"。它等待它,因为它必须继续当前线程。
然后,一旦当前任务完成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 才完成任务。
我最近在 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 中包含的所有内容都必须在到达 return 之前执行,因为 $http.get 是通过 .then 连接的。但是根据调试信息,该函数会遍历 locationCount++ 甚至 return 在它深入之前(意味着在第一个 .then() 之后)的承诺。
这是怎么回事?我是否误解了 AngularJS 概念的这一部分?
或者这真的是一种糟糕的做法,我应该寻求不同的解决方案吗?
如果上下文是 important/interesting:对象基于 https://www.hl7.org/fhir/2015May/location.html#5.15.3
$http.get 是异步的,因此根据(除其他事项外)获取的数据有多大,'complete' 获取所需的时间是可变的。因此,为什么没有说明它们将按什么顺序完成
使用 JavaScript 您只能创建单线程应用程序,尽管例如here他们说不能保证是那样。
但我们谈论的是真实世界和真实浏览器,因此您的代码示例 运行 作为单个线程(顺便说一下,同一线程也用于呈现您的 CSS 和HTML,至少在 Firefox 中是这样。
说到异步调用
$http.get($scope.api + 'Device?_format=json', {
它说 "hey, I can do that later"。它等待它,因为它必须继续当前线程。
然后,一旦当前任务完成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 才完成任务。