在我的控制器中我有一个功能
$scope.orderHistory = {};
$scope.results = {};
var getHistory = function (max,offset)
{
//do some stuff
$scope.orderHistory = data.entities;
angular.forEach($scope.orderHistory,function(value)
{
$scope.results = getResults(value.id);
console.log($scope.results);
});
}
var getResults = function(id)
{
api.getHistoryData(id)
.then ( function (results)
{
return results.data;
});
};
我遇到的问题是getResults函数似乎没有实际返回数据并将其设置为getHistory函数内的$ scope.results。
当我在getResults函数的.then部分中的(results.data)中执行console.log时,我会看到结果。任何人都可以帮助我理解为什么它不会返回结果,即使它存在,我可以做些什么来解决它
答案 0 :(得分:10)
then(function(){...})
中的函数执行asynchronously,包含getResults
函数不会等待它返回。更具体地说,api.getHistoryData
似乎返回promise。
您可以使用Angular的数据绑定解决此问题:
var getHistory = function (max,offset)
{
//do some stuff
$scope.orderHistory = data.entities;
angular.forEach($scope.orderHistory,function(value)
{
getResults(value.id);
});
}
var getResults = function(id)
{
api.getHistoryData(id)
.then ( function (results) {
$scope.results = results.data;
});
};
然后在您的模板中使用以下内容:
<button ng-click="getHistory(0, 0)"></button>
{{results}}
答案 1 :(得分:4)
让我们看看我是否可以澄清承诺是如何运作的,以及可能会让你失望的地方:
当你说:
$scope.results = getResults(value.id);
这意味着,将getResults的返回值分配给 $ scope.results 变量。现在让我们来看看 getResults 函数。
var getResults = function(id) {
api.getHistoryData(id)
.then(function (results) {
return results.data;
});
};
现在注意一些事情:
让我们修改getResults函数来澄清这一点:
angular.forEach($scope.orderHistory, function(value) {
console.log('1 - Get results for ', value.id);
getResults(value.id);
});
var getResults = function(id) {
console.log('2 - GetResults called');
api.getHistoryData(id)
.then(function (results) {
console.log('3 - Get results has data');
return results.data;
});
};
如果我们有类似上面的代码,则首先打印1和2的console.logs,然后在稍后的某个时间点,将所有3个打印在一起。这是因为JavaScript是异步且无阻塞的,这意味着它将继续执行而无需等待响应返回。
因此,为了让它按照您的预期运行,您需要利用AngularJS中的Promise,它允许您知道服务器响应何时返回。它为我们提供了一种跨函数处理异步事件的方法。因此,如果您按如下方式修改代码:
angular.forEach($scope.orderHistory, function(value) {
getResults(value.id).then(function(results) {
$scope.results[value.id] = results.data;
});
});
var getResults = function(id) {
return api.getHistoryData(id);
};
所以我们从 getResults 返回一个promise,然后当promise完成后,我们使用该值并在main函数的$ scope.results中设置它。
希望这会让事情更加清晰。
答案 2 :(得分:1)
我认为你没有正确使用诺言:
$scope.orderHistory = {};
$scope.results = {};
var getHistory = function (max,offset)
{
//do some stuff
$scope.orderHistory = data.entities;
angular.forEach($scope.orderHistory,function(value)
{
// get results returns a promise
// we use the promise to set $scope.results
getResults(value.id).then(function(results){
$scope.results = results.data;
});
});
}
// returns a promise
var getResults = function(id)
{
return api.getHistoryData(id);
};
只有在解决了承诺后才会更改 $scope.results
。
此外,当前编写的方式,$scope.results
将覆盖每个value.id
。如果那不是您的意图,我会将其转换为数组,并将push
每个新值转换为数组。
答案 3 :(得分:1)
让我们明确一点,您的orderHistory
和results
变量是对象,而不是数组。 angular.forEach函数允许您迭代数组和对象属性;它并不意味着被迭代的对象是一个数组。 Elad在说明每次迭代都会覆盖你的结果变量时是正确的。
如果您确实希望保留getResults
函数的所有结果,则需要将结果实例化为数组;并让您的视图反映结果,直接从异步结果将它们推入范围变量。
$scope.orderHistory = {};
$scope.results = [];
var getHistory = function (max,offset)
{
//do some stuff
$scope.orderHistory = data.entities;
angular.forEach($scope.orderHistory,function(value)
{
getResults(value.id);
});
}
var getResults = function(id)
{
api.getHistoryData(id)
.then ( function (results)
{
$scope.results.push(results);
});
};
答案 4 :(得分:0)
只需修复getResults
,将return
添加到其中
var getResults = function(id)
{
return api.getHistoryData(id)
.then ( function (results)
{
return results.data;
});
};
答案 5 :(得分:0)
这是2分。 首先,getResults不返回任何内容,它只是处理promisses链。我们可以更改getResults以返回将返回结果的promiss:
var getResults = function(id)
{
return api.getHistoryData(id)
.then ( function (results)
{
return results.data;
});
};
其次,从角度版本1.2(不完全确定是否从这个版本)角度不能自动解决promisses所以你必须自己做:
angular.forEach($scope.orderHistory,function(value)
{
getResults(value.id).then(function(results){
$scope.results = results;
console.log($scope.results);
})
});
整个代码:
$scope.orderHistory = {};
$scope.results = {};
var getHistory = function (max,offset)
{
//do some stuff
$scope.orderHistory = data.entities;
angular.forEach($scope.orderHistory,function(value)
{
getResults(value.id).then(function(results){
$scope.results = results;
console.log($scope.results);
})
});
}
// returns a promise
var getResults = function(id)
{
return api.getHistoryData(id)
.then ( function (results)
{
return results.data;
});
};