角度控制器功能不会将结果从一个功能返回到另一个功能

时间:2014-08-14 17:53:49

标签: javascript angularjs angularjs-scope

在我的控制器中我有一个功能

$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时,我会看到结果。任何人都可以帮助我理解为什么它不会返回结果,即使它存在,我可以做些什么来解决它

6 个答案:

答案 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;
    });
 };

现在注意一些事情:

  1. getResults函数没有return语句。这意味着getResults没有返回任何内容来分配给$ scope.results。
  2. getResults函数本身发出异步请求。这意味着,如果函数执行时,结果返回时是两个不同的时间点。
  3. 最后,你的return语句不在 getResults 函数内(技术上是),但实际上是在 getResults 函数内的函数内。因此,返回 results.data 适用于功能(结果){} ,而不适用于 getResults
  4. 另外,请注意,如果它按照您的预期工作,那么每次服务器响应时,您都会继续覆盖 $ scope.results 的值。那可能不是你想要的
  5. 让我们修改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)

让我们明确一点,您的orderHistoryresults变量是对象,而不是数组。 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;
        });
 };