在AngularJS的Promise中使用它 [英] Using this within a promise in AngularJS
问题描述
是否有最佳实践解决方案可以在承诺中使用?在jQuery中,我可以绑定我的对象以在我的诺言/回调中使用它-但是在angularJS中呢?是否有最佳实践解决方案?方式"var service = this;"我不喜欢...
Is there a best-practice solution to be able to use within in promise this? In jQuery i can bind my object to use it in my promise/callback - but in angularJS? Are there best-practice solutions? The way "var service = this;" i don't prefer ...
app.service('exampleService', ['Restangular', function(Restangular) {
this._myVariable = null;
this.myFunction = function() {
Restangular.one('me').get().then(function(response) {
this._myVariable = true; // undefined
});
}
}];
是否有针对此问题的解决方案?我如何才能在诺言中通过我的服务访问成员或方法?
Are there solutions for this issue? How i can gain access to members or methods from my service within the promise?
谢谢.
推荐答案
The generic issue of dynamic this
in a callback is explained in this answer which is very good - I'm not going to repeat what Felix said. I'm going to discuss promise specific solutions instead:
Promise是在Promises/A +规范下指定的,它允许Promise库无缝使用彼此的Promise. Angular $ q承诺遵守规范,因此Angular承诺必须根据定义将.then
回调作为函数执行-无需设置this
.在严格模式下,执行promise.then(fn)
总是 将this
评估为在fn
内部未定义(在非严格模式下为window
).
Promises are specified under the Promises/A+ specification which allows promise libraries to consume eachother's promises seamlessly. Angular $q promises honor that specification and therefor and Angular promise must by definition execute the .then
callbacks as functions - that is without setting this
. In strict mode doing promise.then(fn)
will always evaluate this
to undefined inside fn
(and to window
in non-strict mode).
原因是ES6即将来临,并且可以更优雅地解决这些问题.
The reasoning is that ES6 is across the corner and solves these problems more elegantly.
那么,您有什么选择?
- Some promise libraries provide a
.bind
method (Bluebird for example), you can use these promises inside Angular and swap out $q. - ES6, CoffeeScript, TypeScript and AtScript all include a
=>
operator which bindsthis
. - You can use the ES5 solution using
.bind
- You can use one of the hacks in the aforementioned answer by Felix.
以下是这些示例:
假设您已遵循在问题和答案上方应该能够做到:
Assuming you've followed the above question and answer you should be able to do:
Restangular.one('me').get().bind(this).then(function(response) {
this._myVariable = true; // this is correct
});
使用箭头功能
Restangular.one('me').get().then(response => {
this._myVariable = true; // this is correct
});
使用.bind
Restangular.one('me').get().then(function(response) {
this._myVariable = true; // this is correct
}.bind(this));
使用ES5之前的"hack"
var that = this;
Restangular.one('me').get().then(function(response) {
that._myVariable = true; // this is correct
});
当然,还有一个更大的问题
您的当前设计没有任何方法来知道_myVariable
何时可用.您必须对其进行轮询或依靠内部状态排序.我相信您可以做得更好,并设计一个在变量可用时始终执行代码的设计:
Of course, there is a bigger issue
Your current design does not contain any way to _know when _myVariable
is available. You'd have to poll it or rely on internal state ordering. I believe you can do better and have a design where you always execute code when the variable is available:
app.service('exampleService', ['Restangular', function(Restangular) {
this._myVariable =Restangular.one('me');
}];
然后您可以通过this._myVariable.then(function(value){
使用_myVariable
.这似乎很乏味,但是如果您使用$q.all
,则可以轻松地使用多个值来执行此操作,并且就状态同步而言,这是完全安全的.
Then you can use _myVariable
via this._myVariable.then(function(value){
. This might seem tedious but if you use $q.all
you can easily do this with several values and this is completely safe in terms of synchronization of state.
如果您想延迟加载它而不是第一次不调用它(也就是说,仅在调用myFunction时)-我完全可以理解.您可以使用吸气剂并执行以下操作:
If you want to lazy load it and not call it the first time (that is, only when myFunction is called) - I totally get that. You can use a getter and do:
app.service('exampleService', ['Restangular', function(Restangular) {
this.__hidden = null;
Object.defineProperty(this,"_myVariable", {
get: function(){
return this.__hidden || (this.__hidden = Restangular.one('me'));
}
});
}];
现在,仅当您第一次访问它时,它将被延迟加载.
Now, it will be lazy loaded only when you access it for the first time.
这篇关于在AngularJS的Promise中使用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!