Javascript 角度控制器函数不会将结果从一个函数返回到另一个函数

Javascript 角度控制器函数不会将结果从一个函数返回到另一个函数,javascript,angularjs,angularjs-scope,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.result

在我的控制器中,我有一个函数

$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

 var getResults = function(id) {
    api.getHistoryData(id)
        .then(function (results) {
            return results.data;
    });
 };
当我在.getResults函数中执行console.log(results.data)时,我会看到结果。有人能帮我理解为什么它即使存在也不返回结果,以及我能做些什么来修复它

然后执行
中的函数(function(){…})
,包含的
getResults
函数不会等待它返回。更具体地说,
api.getHistoryData
似乎返回一个

您可以使用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}}

{{results}}

我认为您没有正确使用承诺:

$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
将为每个
值.id
覆盖。如果这不是您的意图,我会将其转换为一个数组,并将每个新值推入其中。

请澄清,您的
orderHistory
results
变量是对象,而不是数组。angular.forEach函数允许您迭代数组和对象属性;这并不意味着被迭代的对象是数组。Elad正确地指出,每次迭代都会覆盖results变量

如果要保留
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);
        });
 };

让我们看看我能否澄清承诺是如何起作用的,以及在这里你可能会被什么抛弃:

当你说:

$scope.results = getResults(value.id);
这意味着,将getResults的返回值分配给$scope.results变量。现在让我们看看您的getResults函数

 var getResults = function(id) {
    api.getHistoryData(id)
        .then(function (results) {
            return results.data;
    });
 };
现在注意几件事:

  • getResults函数没有返回语句。这意味着getResults没有返回任何要分配给$scope.results的内容
  • getResults函数本身发出异步请求。这意味着,如果函数执行时和结果返回时是两个不同的时间点
  • 最后,您的return语句不在getResults函数中(从技术上讲是这样),而是在getResults函数中的函数中。因此,返回的results.data用于函数(results){}而不是getResults
  • 另外,请注意,如果它按照您的预期工作,那么每次服务器响应时,您都会覆盖$scope.results的值。那可能不是你想要的
  • 让我们修改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中的承诺,这允许您有一个钩子来知道服务器响应何时返回。它为我们提供了一种跨函数处理异步事件的方法。因此,如果您按如下方式修改代码:

    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返回一个承诺,然后当承诺完成时,我们使用该值并在主函数中将其设置为$scope.results

     var getResults = function(id) {
        api.getHistoryData(id)
            .then(function (results) {
                return results.data;
        });
     };
    

    希望这能让事情更清楚。

    只需修复
    getResults
    ,添加
    return

    var getResults = function(id)
     {
        return api.getHistoryData(id)
            .then ( function (results)
            {
                return results.data;
    
            });
     };
    
    这里有两点。 首先,getResults不返回任何东西,它只是处理一系列的承诺。我们可以将getResults更改为return promiss,它将返回结果:

    var getResults = function(id)
     {
        return api.getHistoryData(id)
            .then ( function (results)
            {
                return results.data;
    
            });
     };
    
    其次,从angular版本1.2(不完全确定是否来自此版本)开始,angular不会自动解析期票,因此您必须自己进行解析:

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

    您需要的是
    $scope.results
    结果数组?是的$scope.results应该是结果,当我执行console.log($scope.results)时,我应该看到从getResults()返回的结果是orderHistory数组还是字典?orderHistory是数组在视图中看到空对象吗?如果你将结果记录在控制台中,意味着你拥有它,并且所有东西都在控制器中工作。不过这与视图无关。我正在尝试从getResults函数中获取结果,并将其用作getHistory的一部分function@Yeak我更新了我的答案,您需要理解异步javascript(请参阅我答案中的第一个链接)才能理解为什么您的方法不起作用。不过我对angular还不熟悉,你的回答并没有真正告诉我如何解决这个问题。我的意思是,你还需要知道什么是回调函数和承诺。另外,只要你不告诉我为什么我的答案对你不起作用,我就无能为力了……这个答案是正确的……你不能从
    中的回调中返回值,然后
    对于
    api.getHistoryData
    ,并期望
    getResults
    将其返回到
    getHistory
    。。。