无法将 http 结果保存到范围
Can't save http result to scope
我定义了一个 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 ;
});
}
}
})
稍后在我的控制器中,我在 loadData()
函数中调用 getAllData()
:
.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.loadData()
调用之前定义 $scope.myData
(请参阅代码中的注释)。不幸的是,这个简单的变量声明让我的应用程序完全冻结。我还没有找到原因。另外,我不确定这是否与我的整体问题有关。
所以我错过了什么?为什么我无法将我的 "http get" 结果存储在控制器的 $scope
中?
编辑:所以在我的例子中,我需要在使用当前控制器之前就把数据放在那里。将控制器内执行的所有代码放入承诺的 .then
链中是否是一个合法的选择?
你错过了一个承诺$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;
}
}
})
这是因为您的 HTTP 请求是异步函数,而赋值 $scope.another_var = $scope.myData;
是同步的。
基本上发生的事情是,当您的 QuizCtrl
控制器加载时,它会在完成 getAllData()
的 http 请求之前完成语句 $scope.another_var = $scope.myData;
。你得到的是 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();
希望这对您有所帮助。
如果您需要根据已经在范围内的值更新不同的值,您可以观察更改的值并相应地更新。
这是你可以做的。
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>
我定义了一个 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 ;
});
}
}
})
稍后在我的控制器中,我在 loadData()
函数中调用 getAllData()
:
.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.loadData()
调用之前定义 $scope.myData
(请参阅代码中的注释)。不幸的是,这个简单的变量声明让我的应用程序完全冻结。我还没有找到原因。另外,我不确定这是否与我的整体问题有关。
所以我错过了什么?为什么我无法将我的 "http get" 结果存储在控制器的 $scope
中?
编辑:所以在我的例子中,我需要在使用当前控制器之前就把数据放在那里。将控制器内执行的所有代码放入承诺的 .then
链中是否是一个合法的选择?
你错过了一个承诺$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;
}
}
})
这是因为您的 HTTP 请求是异步函数,而赋值 $scope.another_var = $scope.myData;
是同步的。
基本上发生的事情是,当您的 QuizCtrl
控制器加载时,它会在完成 getAllData()
的 http 请求之前完成语句 $scope.another_var = $scope.myData;
。你得到的是 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();
希望这对您有所帮助。
如果您需要根据已经在范围内的值更新不同的值,您可以观察更改的值并相应地更新。
这是你可以做的。
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>