设置$ scope变量时,无法获取$ http.get返回的当前值,只能获取前一个值

时间:2016-07-20 18:19:24

标签: javascript angularjs angularjs-scope

我有一个角度视图,其中包含一个由选择列表和文本框组成的行表。当更改选择列表索引时,我需要使用数据库中的查找值更新同一行上的相应文本框。我在选择列表上使用ng-Change调用$ scope函数,该函数利用$ http.get通过ActionMethod进行调用。我已经用百万种方式尝试了这个,最后能够通过将$ http.get函数赋值给范围变量来从$ http.get函数中提取一个值,但是我只得到由所选索引更改触发的先前查找的值,不是现在的。我怎样才能实时获得价值?我知道它是异步的,所以我知道问题的本质。我该如何解决?我的.js的当前状态:

$scope.EntityId = null; 
$scope.EntityNameChanged = function (item, block) {
    for (var i = 0; i < block.length; i++)
    {
        if (item.Value == block[i].Name.Value) {
            $scope.GetEntityId(item.Value);
            block[i].Id = $scope.EntityId;
        }
    } 
} 
$scope.GetEntityId = function(name) {
    $http.get("EntityId", { params: { EntityName: name } }).then(function success(response) {
        $scope.EntityId = response.data[0].Value;
    }); 
};

3 个答案:

答案 0 :(得分:0)

要提示Angular在其$ watch循环上更新范围的值,请在分配后调用$scope.apply()。这应该会带给你最近的价值。

编辑:这个答案错了​​。这是$ http get请求,已经使用$ apply。 您需要做的是将请求放入工厂并返回承诺。需要在控制器中出厂。

    app.factory('getData', function ($http, $q){

    this.getlist = function(){            
        return $http.get('mylink', options)
            .then(function(response) {
              return response.data.itemsToReturn;
            });            
    }
    return this;
});

app.controller('myCtrl', function ($scope, getData){
    app.getData()
      .then(function(bar){
         $scope.foo = bar;
       });
});

答案 1 :(得分:0)

您的GetEntityId函数不是异步的,即使它发出异步请求。在设置$scope.EntityId时,for循环已经退出。

你实际上不能像这样排队异步调用,因为它们中的每一个都试图在循环之外共享一个可以由任何其他迭代设置的值,因此循环中的一个项可能会得到另一个项目& #39; s返回值。

相反,您应该将promise返回循环,并在循环中执行.then。如下所示:

$scope.EntityNameChanged = function(item, block) {
  for (var i = 0; i < block.length; i++) {
    if (item.Value == block[i].Name.Value) {
      $scope.GetEntityId(item.Value)
        .then(function success(response) {
          block[i].Id = response.data[0].Value;
        });
    }
  }
}
$scope.GetEntityId = function(name) {
  return $http.get("EntityId", {
    params: {
      EntityName: name
    }
  });
};

(注意这是未经测试的,但应该按照您的预期进行)。

答案 2 :(得分:0)

GetEntityID函数应该返回一个承诺

function GetEntityId(name) {
    //save httpPromise
    var p = $http.get("EntityId", { params: { EntityName: name } });

    //return derived promise
    return p.then(function onSuccess(response) {
        //return chained data
        return response.data[0].Value;
    }); 
};

然后在for循环中使用IIFE

$scope.EntityNameChanged = function (item, block) {
    for (var i = 0; i < block.length; i++) {
        //USE IIFE to hold value of i
        (function IIFE(i) {
            if (item.Value == block[i].Name.Value) {
                //save promise
                var p = GetEntityId(item.Value);
                //extract value from promise
                p.then(function onSuccess(Value) {
                     block[i].Id = Value;
                });
            }
        })(i); 
    }
} 

因为在onSuccess循环完成后异步调用for函数,所以在从服务器返回数据之前,需要使用IIFE闭包来保留i的值。 / p>