Не удается сохранить результат http в область

У меня определен json-файл, и я пытаюсь загрузить один из моих контроллеров. Я использую фабрику для получения данных:

.factory('myService', function($http) {

  var all_data = [];

    return {
      getAllData: function(){
        return $http.get('js/data/all_data.json').then(function(data) {
          all_data  = data;
          return all_data ;
      });
        }
    }
})

Позже в моем контроллере я звоню getAllData() в loadData()-функции:

.controller('QuizCtrl',['$scope','$state','$http','myService',function($scope,$state,$http,myService){

    // $scope.myData = []; <-- this makes the app freeze and not respond anymore
    $scope.loadData = function(){
      myService.getAllData().then(function(all_data){
          $scope.myData = all_data.data.all_data;
          alert($scope.myData);
      });
    }

    $scope.loadData();
    $scope.another_var = $scope.myData;

}])

Как видите, в первую очередь я также звоню loadData(), Во время отладки внутри функции (см. alert()) Я ясно вижу, как JSON был загружен и применен к $scope.myData переменная.

Однажды я пытаюсь присвоить переменную другой переменной (см. $scope.another_var) myData не определено.

То, что я пытался определить $scope.myData перед $scope.loadData() позвонить (см. комментарий в коде). К сожалению, это простое объявление переменной полностью останавливает мое приложение. Я еще не нашел причину этого. Кроме того, я не уверен, связано ли это с моей общей проблемой.

Так что я пропустил? Почему я не могу сохранить результат "http get" в контроллере $scope?

РЕДАКТИРОВАТЬ: Таким образом, в моем случае, мне нужно, чтобы данные были там, прежде чем текущий контроллер даже используется. Будет ли правильным вариантом поместить весь код, который выполняется внутри контроллера, в .thenцепь обещания?

3 ответа

Решение

Это потому, что ваш HTTP-запрос является асинхронной функцией при назначении $scope.another_var = $scope.myData; является синхронным.

В основном, что происходит, когда ваш QuizCtrl Контроллер загружен, он завершает оператор $scope.another_var = $scope.myData; до завершения http-запроса getAllData(), То, что у вас есть, это состояние гонки.

Если вы хотите изменить значение another_var переместите его в свой асинхронный обратный вызов:

$scope.loadData = function(){
      myService.getAllData().then(function(all_data){
          $scope.myData = all_data.data.all_data;
          alert($scope.myData);

          // because now $scope.myData is available this assignment will work:
          $scope.another_var = $scope.myData;
      });
    }

$scope.loadData();

Надеюсь это поможет.

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

вот что ты мог сделать.

var app = angular.module("sampleApp", []);

app.controller("sampleController", ["$scope", "sampleService",
  function($scope, sampleService) {

    sampleService.sampleMethod(1).then(function(value) {
      $scope.value = value;
      $scope.$digest();
    }, function(error) {});

    $scope.$watch(function() {
      return $scope.value;
    }, function(newValue, oldValue) {
      //Default Value when the dependant value is not available
      newValue = newValue || 0;
      $scope.myNewValue = newValue * 10;
    });

  }
]);

app.service("sampleService", function() {
  this.sampleMethod = function(value) {
    var promise = new Promise(function(resolve, reject) {
      setTimeout(function() {
        value = value * 2;
        resolve(value);
      }, 1000);
    });
    return promise;
  };
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="sampleApp">
  <div ng-controller="sampleController">
    <div>Value: {{value}}</div>
    <div>Cloned Value : {{myNewValue}}
    </div>
  </div>
</div>

Вы пропускаете обещание $q

возьмите этот метод например:

.factory('myService', function($http,$q) {
    var all_data = [];
    return {
        getAllData: function () {
            var d = $q.defer();
            $http.get('js/data/all_data.json')
                .success(function (response) {
                    d.resolve(response);
                });
            return d.promise;
        }
    }
})
Другие вопросы по тегам