Невозможно получить текущее значение, возвращаемое $ http.get при установке переменной $ scope, только предыдущее значение

0

У меня есть угловой вид, который имеет таблицу строк, состоящую из списка выбора и текстового поля. Когда индекс списка выбора изменяется, мне нужно обновить соответствующее текстовое поле в той же строке с помощью значения поиска из базы данных. Я использую ng-Change в списке выбора для вызова функции $ scope, которая использует $ http.get для вызова через ActionMethod. Я пробовал это в миллион способов и, наконец, смог извлечь значение из функции $ 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;
    }); 
};
Теги:
angularjs-scope

3 ответа

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

Затем используйте IIFE в цикле for.

$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 до тех пор, пока данные не будут возвращены с сервера.


  • 0
    Вы ракетист со стальными глазами! Ты понял! Большое вам спасибо: D
0

Функция GetEntityId не является асинхронной, даже если она выполняет асинхронный запрос. к тому времени, когда он устанавливает $scope.EntityId, цикл for уже вышел.

Вы не можете на самом деле очереди асинхронных вызовов, например, потому что каждый из них пытается поделиться значением вне цикла, которое может быть установлено любой другой итерацией, поэтому один элемент в цикле может получить другое возвращаемое значение элемента.

Вместо этого вы должны вернуть обещание обратно в цикл и выполнить ваш. .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
    }
  });
};

(обратите внимание, что это не проверено, но должно делать то, что вы ожидаете).

  • 0
    Спасибо вам большое за ваш ответ. Это похоже на то, что у меня было вначале, и я получаю ту же проблему при попытке использовать этот метод: «Невозможно установить свойство« Id »из неопределенного. Кажется, блок недоступен в функции $ http.get.
  • 0
    хм, block определенно должен быть доступен в .then , если .then находится внутри цикла; Возможно, я смогу создать тестируемый пример позже.
0

Чтобы заставить Angular обновить значение области в цикле $ watch, вызовите $scope.apply() после назначения. Это должно привести к последнему значению.

EDIT: Этот ответ был неправильным. Это запрос $ 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;
       });
});
  • 0
    Большое спасибо за ответ. $ scope.apply () недопустимо, но $ scope. $ apply () было. Однако это создало каскад ошибок $ rootcope.
  • 0
    Извини, моя ошибка. Я буду редактировать с некоторым кодом

Ещё вопросы

Сообщество Overcoder
Наверх
Меню