我在AngularJS中理解承诺时遇到了问题。
我有以下内容:
var loader = angular.module('loadIt', []);
loader.factory('loadService', function($http, $q) {
return {
getJs: function(path) {
var deferred = $q.defer();
$http.get(path).then(function(response) {
deferred.resolve(response.data);
});
return deferred.promise;
}
}
});
var myMod = angular.module('myMod', ['loadIt']);
myMod.service('mymodService', function(loadService) {
this.vals = {};
this.readIt = function (pos) {
this.vals[pos] = loadService.getJs('aaa.js');
}
});
在调试器中,我看到了这一行:
this.vals[pos] = loadService.getJs('aaa.js');
getJs()调用返回正确的值。 但范围是错误的。 this.vals未在readIt函数内定义。 我该如何解决这个问题?
修改
我也尝试了以下内容:
this.readIt = function (pos) {
loadService.getJs('aaa.js').then(function(data) {
this.vals[pos] = data;
});
}
在这里,我看到数据包含从文件中读取的JSON对象。
这指的是对象Window,this.vals在范围内不存在。
答案 0 :(得分:2)
由于您选择使用服务(而不是工厂),因此您需要将this
分配给另一个变量(通常为self
,如下所示),如果您希望从另一个功能的范围。否则,this
回调函数中then
的上下文发生变化的事实是有问题的。
myMod.service('mymodService', function(loadService) {
this.vals = {};
var self = this;
this.readIt = function (pos) {
loadService.getJs('aaa.js').then(function(data){
self.vals[pos] = data;
});
}
});
使用上面的代码,您可以设置范围变量,如下所示:
myMod.controller('MyController', function($scope, mymodService, $timeout){
mymodService.readIt(0);
$scope.vals = mymodService.vals;
})
如果您发现此方法最初不适合您,请将this demo与您的代码进行比较,并考虑您可能需要重构的内容。
附加说明:
如果您不喜欢var self = this
语法,请考虑使用工厂而不是服务:
myMod.factory('mymodService', function(loadService) {
var modservice = {
vals: {}
};
modservice.readIt = function (pos) {
loadService.getJs('aaa.js').then(function(data){
modservice.vals[pos] = data;
});
}
return modservice;
});
答案 1 :(得分:2)
这里有2个潜在问题。
1)loadService.getJs()
返回一个承诺。因此,您要为this.vals[pos]
分配承诺,而不是实际值。假设您想要分配实际值,那么您需要
loadService.getJs().then(function(data) {
this.vals[pos] = data;
});
2)this
指的是调用上下文。所以在readIt()
this
中将引用任何称为它的对象 - 而不是它在(在这种情况下为mymodService
)中定义的词法范围。但您可以使用bind()
来解决此问题。 bind
允许我们强制执行函数时绑定的this
。因此,在回调结束时添加bind()
,您的代码现在看起来像:
this.vals = {};
this.readIt = function (pos) {
loadService.getJs().then(function(data) {
this.vals[pos] = data;
}.bind(this));
}
this
可能会非常棘手 - 如果您想了解更多细节,可以结帐this blog by Dan Wahlin
这是一个精简版fiddle,其中包含两项更改,显示所有内容都在视图$ scope中连接。