Javascript AngularJS对象在控制器方法中丢失值
我是一名初级开发人员,所以我可能遗漏了一些明显的东西,但我感觉有点疯狂。我有一个简单的角度网络应用程序。我正在尝试加载与主机数组相对应的环境名称的哈希字典<代码>{development:[“dev.8090”,“host.dev.9009”]}然后使用该字典查找我当前所在的主机。我应该能够将location.host变量传递给getEnv方法,并找到相关键,该键将告诉我所处的环境 字典会加载,但当我尝试在getEnv方法内部访问它时,它会恢复为空对象。提醒你,不是没有定义,而是空的。这是我的密码:Javascript AngularJS对象在控制器方法中丢失值,javascript,angularjs,angularjs-scope,javascript-objects,Javascript,Angularjs,Angularjs Scope,Javascript Objects,我是一名初级开发人员,所以我可能遗漏了一些明显的东西,但我感觉有点疯狂。我有一个简单的角度网络应用程序。我正在尝试加载与主机数组相对应的环境名称的哈希字典{development:[“dev.8090”,“host.dev.9009”]}然后使用该字典查找我当前所在的主机。我应该能够将location.host变量传递给getEnv方法,并找到相关键,该键将告诉我所处的环境 字典会加载,但当我尝试在getEnv方法内部访问它时,它会恢复为空对象。提醒你,不是没有定义,而是空的。这是我的密码: v
var app = angular.module('app', ['ngResource', 'ui.bootstrap', 'ui.router']);
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
function AppController($scope, $http) {
window.MY_SCOPE = $scope;
$scope.env = "Local";
$scope.dict = {};
$scope.loadDict = function() {
$http.get('api/call/').
success(function(data){
for (env in data.environment) {
// data.environment = array of objects
// [
// {hosts: ["host1", "host2"], name: "string1"},
// {hosts: ["host1", "host2"], name: "string2"}
// ]
var key = data.environment[env].name;
$scope.dict[key] = data.environment[env].hosts;
}
console.log($scope.envDict)
// in the console:
// Object {string1: Array[2], string2: Array[2]}
}).error(function(data){
console.error(data);
})
};
$scope.getEnv = function(host) {
for (key in $scope.dict) {
// never gets this far because $scope.dict is now = {}
for (value in $scope.dict[key]) {
if ($scope.dict[key][value] === host) {
$scope.env = key;
}
}
}
};
$scope.loadDict();
$scope.getEnv("host1");
}
我可以手动调用这些方法中的每一个,并使用MY_SCOPE变量从控制台获得所需的结果。如果我硬编码字典,它会工作。如果我从代码中的任何位置(除了$scope.getEnv函数内部)输入console.log$scope.dict,就会得到预期的结果。只要涉及$scope.getEnv,$scope.dict={}
我努力把这些钥匙编入字典。我尝试在代码中移动定义。我已经尝试将loadDict方法导出到工厂中。都没有用。想法?在
$scope.loadDict
中调用$http.get是异步的。在加载词典之前调用getEnv。一旦数据返回,您需要调用getEnv
让loadDict返回$http.get
呼叫,该呼叫将给您一个承诺。然后,你就可以通过成功的回调来实现这一承诺
您还应该将$http调用放在某种服务中,以“角度”方式执行:)
请尝试以下方法:
$scope.loadDict = function() {
return $http.get('api/call/').
success(function(data){
for (env in data.environment) {
var key = data.environment[env].name;
$scope.dict[key] = data.environment[env].hosts;
}
console.log($scope.envDict)
// in the console:
// Object {string1: Array[2], string2: Array[2]}
}).error(function(data){
console.error(data);
})
};
$scope.loadDict().then(function(result){
$scope.getEnv("host1");
}
您的问题是,您没有处理loadDict在内部是异步的这一事实 解决这个问题的一种方法是等待它完成,返回一个承诺,然后等待这个承诺得到解决 还有其他方法可以做到这一点,但这可能是最接近您已有的方法之一:
// inject $q so you can make a promise
function AppController($scope, $http, $q) {
window.MY_SCOPE = $scope;
$scope.env = "Local";
$scope.dict = {};
$scope.loadDict = function() {
// set up the deferred response
var deferred = $q.defer();
$http.get('api/call/').
success(function(data){
for (env in data.environment) {
// data.environment = array of objects
// [
// {hosts: ["host1", "host2"], name: "string1"},
// {hosts: ["host1", "host2"], name: "string2"}
// ]
var key = data.environment[env].name;
$scope.dict[key] = data.environment[env].hosts;
}
console.log($scope.envDict)
// in the console:
// Object {string1: Array[2], string2: Array[2]}
// all is well so resolve the promise
deferred.resolve();
}).error(function(data){
console.error(data);
// reject the promise
deferred.reject(data);
})
return deferred.promise;
};
$scope.getEnv = function(host) {
for (key in $scope.dict) {
// never gets this far because $scope.dict is now = {}
for (value in $scope.dict[key]) {
if ($scope.dict[key][value] === host) {
$scope.env = key;
}
}
}
};
$scope.loadDict().then(
function () {
$scope.getEnv("host1");
},
function (err) {
// whatever you want to do if the loadDict function failed to do its job
}
);
}
在$http.get()返回数据之前调用了$scope.getEnv()。您需要在$http.get().success()块中调用$scope.getEnv(),如下所示:
$scope.loadDict = function() {
$http.get('api/call/').success(function (data) {
for (env in data.environment) {
var key = data.environment[env].name;
$scope.dict[key] = data.environment[env].hosts;
}
$scope.getEnv("host1");
}).error(function(data){
console.error(data);
});
};
你需要异步处理事情。success是异步回调,而getEnv是同步回调。 本例中的解决方案是在loadDict中定义一个承诺,并在成功调用时解决它。 然后,在控制器getEnv方法中,您将在promise解析后编写代码: 大致代码是这样的,我没有测试它,只是写了一些想法:
$scope.loadDict = function() {
var deferred = $q.defer(); // to define a promise
$http.get('api/call/').
success(function(data){
deferred.resolve(data);//resolve the promise on success
}
}).error(function(data){
console.error(data);
})
return deferred.promise;//return promise
};
$scope.getEnv = function(host) {
$scope.loadDict().then(
function(data) {
for (env in data.environment) {
// data.environment = array of objects
// [
// {hosts: ["host1", "host2"], name: "string1"},
// {hosts: ["host1", "host2"], name: "string2"}
// ]
var key = data.environment[env].name;
$scope.dict[key] = data.environment[env].hosts;
for (key in $scope.dict) {
// never gets this far because $scope.dict is now = {}
for (value in $scope.dict[key]) {
if ($scope.dict[key][value] === host) {
$scope.env = key;
}
}
}
});
};
非常感谢你。我显然有很多东西要学——你能推荐一个可靠的资源来学习承诺吗?我已经浏览了文档,仍然很模糊。我下面链接的$q页面可能会有所帮助——这就是angular的承诺实现。我喜欢的一个更一般的介绍是$Q所基于的原始Q库:(但请注意,并不是所有的Q方法都在$Q中)。两者都可以@link64显然跳过了包装承诺的创建,所以您可能更喜欢它。您仍然应该学习$q,因为您对承诺感到好奇。@stu.salsbury您不确定他是否投票否决了您,他是一个新用户,所以让我们给他一个怀疑的好处=)