Не удается сохранить результат 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;
}
}
})