我有以下问题: 我试图从MongoDB的两个集合中“合并”数据。 一切都看起来不错,直到我尝试显示第二个查询之后的第一个数据:
$scope.getData = function() {
var pipeline, fromDateRangeStatement, toDateRangeStatement, service, joblist;
service = ($scope.service && $scope.service.value) ? $scope.service.value : {
$exists: true
};
pipeline = $scope.utils.getSessionUsersPipeline($scope.fromDate, $scope.toDate,
$scope.checkedResults, $scope.checkedStatuses, service, $stateParams, $scope.usersLimit);
toApi.post("/users/aggregate", {
pipeline: pipeline
}).success(function(data) {
$scope.users = data.data.result;
for (var i = 0; i < $scope.users.length; i++) {
var path = "/jobs/" + scope.users[i].id + "/sessions";
var user = $scope.users[i]
toApi.get(path).success(function(data) {
user.error = data.data.records[0].exception // this is not shows up in HTML!
console.log(data.data.records[0].exception); // but it can be logged!
})
}
})
};
所以,问题是:$scope.users
在我的网页上呈现,而他们的属性error
却没有。在我为for循环中的每个用户更改属性之前,看起来数据已呈现。
如何处理?
感谢
答案 0 :(得分:3)
以下是两种不同的解决方案
您的每个GET请求都是异步的,因此您需要等待所有这些请求解决。您可以将每个请求包装在自己的Promise中,并收集所有Promise,如此
var promises = [];
for (var i = 0; i < $scope.users.length; i++) {
promises[i] = new Promise(function (resolve, reject) {
var path = "/jobs/" + scope.users[i].id + "/sessions";
var user = $scope.users[i]
toApi.get(path).success(function(data){
user.error = data.data.records[0].exception;
console.log(data.data.records[0].exception);
resolve(user);
})
}
然后使用Promise.all()将所有承诺组合为一个Promise并等待它解决。
Promise.all(promises).then(function(users) {
$scope.users = users;
});
简单示例:http://codepen.io/C14L/pen/QNmQoN
尽管如此,更简单,更好的解决方案是逐个显示用户,因为他们的API调用返回
for (var i = 0; i < $scope.users.length; i++) {
var path = "/jobs/" + $scope.users[i].id + "/sessions";
toApi.get(path).success(function (data) {
$scope.users[i].error = data.data.records[0].exception;
$scope.users[i].done = true;
console.log(data.data.records[0].exception);
});
}
只需在模板中添加$scope.users[i].done = true
支票,然后显示带有ng-show="user.done"
的数据集。
答案 1 :(得分:1)
var user = $scope.users[i]
仅指定$scope.users[i]
的值。所以稍后当你user.error=...
时,它不会改变$scope
。试试这个:
for (var i = 0; i < $scope.jobs.length; i++) {
var path = "/jobs/" + scope.users[i].id + "/sessions";
toApi.get(path).success(function(data){
$scope.users[i].error = data.data.records[0].exception // this is not shows up in HTML!
console.log(data.data.records[0].exception); // but it can be logged!
})
}
答案 2 :(得分:1)
关于处理此问题的2个要素:
如果您使用{{value}},请将此替换为
<span ng-bind="value"></span>
所以你不会看到括号。
现在,您希望在更改任何内容之前等待所有请求,以便不显示部分数据。这也很容易:
var promiseArray = [];
for (var i = 0; i < $scope.users.length; i++) {
var path = "/jobs/" + scope.users[i].id + "/sessions";
var user = $scope.users[i]
promiseArray.push(toApi.get(path)).success(function(data){
var result = {i:i, data:data};
return result
});
}
$q.all(promiseArray).then(function success(result){
for(var i=0; i < promiseArray.length;i++){
$scope.users[result.i].error = result.data.data.records[0].exception;
}
});
基本上我在等待所有请求在更改任何数据之前被重新转发,因此这将在相同的角度循环中运行。所以DOM只刷新一次,用户不会看到任何部分结果。