AngularJS对象在控制器方法内丢失值
AngularJS object losing value inside controller method
我是一名初级开发人员,所以我可能错过了一些明显的东西,但我感觉有点疯狂。我有一个简单的Angular网络应用程序。我正在尝试加载一个与主机数组相对应的环境名称的哈希字典。{development: ["dev.8090", "host.dev.9009"]}
,然后使用该字典来查找我当前所在的主机。我应该能够将location.host变量传递给getEnv方法,并找到将告诉我所处环境的关联键。
字典加载,但当我尝试在getEnv方法内部访问它时,它会恢复为一个空对象。请注意,不是没有定义,而是空的。这是我的代码:
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
}
);
}
$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中定义一个promise,并在成功调用时解决它。然后,在控制器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;
}
}
}
});
};
- 序列化数据属性中对象的最可靠方法
- 有没有一种方法可以添加相同的项目val=“0”;4〃;到JavaScript中数组的每个对象
- 如何从对象的原型方法访问JavaScript对象属性
- 为什么不推荐使用“with”?是否有更好或其他方法可以“下降”到对象的命名空间
- 设置嵌套对象属性的更好方法
- JQuery示例不起作用-“;对象没有't支持属性或方法'按钮'&”;
- 对象不支持属性或方法“自动完成”
- call()和apply()实际上是用来欺骗方法处理类似数组的对象的
- 对象文字方法上的Javascript绑定不起作用
- Meteor应用程序无法运行-对象#<编译器>没有方法'主机'
- 为什么我可以在Array属性对象中找到Javascript Array for Each方法
- Underscore.js某些对象的所有方法的总和
- 对象#<XMLHttpRequest>没有方法'完成'
- Es6:能够在设置/更新/删除对象属性时调用自定义方法
- 丢失对象“;这个“;方法中的上下文
- 如何在ajax中调用javascript对象的方法
- 为什么页面方法对象未定义
- 如何使用在另一个文件中定义的JavaScript方法/对象
- 如何告诉JsHint忽略“未解析的函数或方法”?对象上的警告
- 使用jinja/javascript动态创建方法/对象