所以我们都知道 'this' 在 JavaScript 中是一个棘手的关键字,而匿名函数和 AngularJS 承诺让它变得更加棘手。
问题(TL&DR 版本)
允许承诺回调使用与发起请求的服务相同的“this”的正确(和角度)方式是什么?
看这个小提琴的例子:
http://jsfiddle.net/tpeiffer/CFD3e/
控制器上的所有这些方法都调用了 Tier1Service。Tier1Service 然后调用 WorkerService 来获取数据。加载数据时,它通过向 Tier1Service 的承诺返回所述数据。返回的数据被设置到 Tier1Service_data 属性中。
替代 3 很干净并且有效,但感觉必须有更好的方法。
替代 4 也非常干净并且可以工作,但它似乎又是错误的。
现在我真正想要的是 $q 承诺为我做这一切。:)
以下是相关代码:
// App.js
angular.constructor.prototype.call = function (scope, func) {
return function () {
func.apply(scope, arguments);
};
};
// Tier1Service
get coolData() {
return this._data;
},
set coolData(val) {
this._data = val;
},
doWorkAlt1: function () {
mySubWorkerService.someData.then(function (data) {
// FAILS because 'this' is the window,
// not the service
if (data) this._data = data;
});
},
doWorkAlt2: function () {
mySubWorkerService.someData.then((function (data) {
// FAILS because data is undefined because
// the function is wrapped in an anonymous
// function
if (data) this._data = data;
}).call(this));
},
doWorkAlt3: function () {
// WORKS because I keep track of the instance
var instance = this;
mySubWorkerService.someData.then(function (data) {
if (data) instance._data = data;
});
},
doWorkAlt4: function () {
// WORKS because I keep pass 'this' around
mySubWorkerService.someData.then(angular.call(this, function (data) {
if (data) this._data = data;
}));
}
// WorkerService
get someData() {
var deferred = $q.defer();
deferred.resolve('i got back data!!');
return deferred.promise;
}