在AngularJS的Promise中使用它 [英] Using this within a promise in AngularJS

查看:97
本文介绍了在AngularJS的Promise中使用它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有最佳实践解决方案可以在承诺中使用?在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 binds this.
  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆