2016-11-01 4 views
3

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

.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 является «undefined».

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

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

EDIT: В моем случае мне нужны данные, которые должны быть там до того, как будет использоваться текущий контроллер. Будет ли законным вариантом поставить весь код, который выполняется в контроллере, в .then-цепочку обещаний?

ответ

2

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

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

Если вы хотите изменить значение 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(); 

Надеется, что это помогает.

0

Вы пропускаете PROMISS $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; 
     } 
    } 
}) 
+0

К сожалению, это не решает проблему @Marc Расмуссен –

+0

@ Käsebrot Не могли бы вы оставить скрипку или что-то подобное, то иль с удовольствием смотреть его и сделать его работу. Im 100% уверен, что это имеет какое-то отношение к promiss –

0

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

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

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>