2016-03-24 13 views
10

sınıfım var. Zaman aşımı içinde bir kaç iş yapmam gerekiyor. Karşılaştığım problem, zaman aşımı içindeki http değişkenin tanımsız olduğunu söylemesidir.Değişken iç setTimeout undefined olduğunu, ancak dışarısı tanımlandığında

export class MyClass { 

    http:Http: 

    constructor(private http:Http) { 
     this.http = http; 
    } 

    sendFriendRequest(){ 

    this.http.post(...//http variable is defined here 
      setTimeout(function(){ 
       this.http.post(... //http is not defined here 
     } 
    } 
} 
+7

Bu 'bağlam' çünkü: http://stackoverflow.com/questions/2130241/pass-correct-this-context-to-settimeout-callback – nikoskip

+4

Bu soruya gerçekten cevap vermek için 4 cevaba gerçekten ihtiyacımız var mı? "Bu" bağlamı "uygun" almak için ok işlevini kullanın? –

+3

@MarkRajcok evet, 3 cevap ile yeterli değil! –

cevap

19

Bunun nedeni setTimeout içine geri arama işlevi, farklı bir sözlü ortamla içinde olmasıdır. Bu nedenle ES6 + işlevlerinde => kullanılarak tanımlanabilir. Bu, bir işlev içindeki kodun işlevle aynı kapsamı paylaşmasıdır. ES5 sözdizimi ile veya

setTimeout(() => { 
    this.http.post(...) 
}); 

:

Bunu düzeltmek için, sen nereye yerine function(a,b,args) {...} size (a,b,args) => {...} kullanırsınız ES6 + sözdizimi kullanabilirsiniz ya

var root = this; 

setTimeout(function(){ 
    root.http.post(...) 
} 

Umut bu yardımcı olur!

6

Buradaki varlığı korumak için ok işlevini burada kullanmalısınız. Böylece

setTimeout(()=>{ 
    this.http.post(... //http is not defined here 
}) 

, işlev içinde this dış bağlama bağlıdır. Bu sorunla ilgili function(){...

2 en popüler yolu kullanırken değil aynı thissetTimeout içeride

setTimeout(function(){ 
    this.http.post(); 
}.bind(this)); 
2

:

1) dışında "bu" saklamak için fazladan değişken kullanın gibi aynıdır

var that = this; 
this.http.post(...//http variable is defined here 
      setTimeout(function(){ 
       that.http.post(... //http is not defined here 
     } 
    } 

2) ok fonksiyonlarını kullanabilmek

this.http.post(...//http variable is defined here 
      setTimeout(() => { 
       that.http.post(... //http is not defined here 
     } 
    } 

1 yol ES5 yaşında ve herhangi bir derleyiciye ihtiyacınız yok, ES6 sürümü için (# 2) babel gibi bir şey kullanmanız gerekecek.

ok işlevleri hakkında daha fazla bulmak buraya & babel: https://babeljs.io/docs/learn-es2015/

+0

Bilgi için teşekkürler! – user2924127

3

JavaScript'te, this anahtar sözcüğü, bir işlevin çağrıldığı context erişim noktasına erişmek için kullanılır. Javascript'teki işlevler, 'use strict' bayrağı geçerli kapsamda ayarlanmadığı sürece, .methodName() sözdizimini kullanarak veya kullanmadan bunları çağırıp çağırmamanız bağlamında her zaman çağrılır. 'use strict' bayrak ayarlanmadığı sürece

myFunction() 

bağlam küresel pencere nesnesi olmaya çalışma zamanı tarafından kabul edilir (bu durumda bağlam olacaktır: bir işlev böyle bir bağlam olmadan çağrılır

undefined.)

Not: ES6'yı Babel gibi bir aktarıcıyla kullanırken, çıktıda varsayılan olarak katı mod ayarlanır.

Bir işlevin bir başvurusu bir nesneye kaydedildiğinde, bu işlevi nokta sözdizimini kullanarak 'bu' bağlamı olarak nesneyle birlikte çağırabilirsiniz.

var myObj = { 
    myFunc: function(){} 
}; 

// myFunc invoked like this, the value of 'this' inside myFunc will be myObj. 
myObj.myFunc(); 

'bu' işleyin:

Çağrı ve

Hep .call veya .apply yöntemlerle onu çağırarak bir fonksiyonu bağlamını değiştirebilirsiniz uygulayın. Bu durumda, sizin tarafınızdan çağrılmayan, ancak setTimeout işlevi tarafından çağrılan anonim bir işleve sahipsiniz. Bu nedenle, .call veya .apply'dan yararlanamayacaksınız.

Bind

Bunun yerine, .bind yöntemini kullanarak Özel bir bağlam sahip yeni işlev oluşturabilirsiniz. .bind() işlevini anonim işlevinize çağırarak, özel içeriğinizin 'buna' bağlı olduğu yeni bir işlev döndürülür. Bu şekilde özel bağlı fonksiyonunuzu setTimeout'a veri olarak geçirebilirsiniz. Anonim işlevin içinde 'this' anahtar sözcüğünün doğru değere bağlı olması gerekir. 'Bu'

Sözcük:

ES6 olarak, fakat, ok fonksiyonu 'bu' değişiklikle ilgili kurallar kullanırken. Eğer bu sözdizimini kullanırsanız, 'bu' bağlamının mevcut kapsamda olduğu gibi aynı kalacağını göreceksiniz.

setTimeout(() => { 
    // Hey I can access 'this' in here! 
}, 1000); 

bir başvuru Kaydetme:

Eğer Babel derlenen çıkışta bakarsanız Babil benzeri _this1, _this2 ve birlikte 'bu' başvurular kaydederek bağlamda izler göreceksiniz.

var self = this; 
setTimeout(function(){ 
    self.http.post... 
}); 

Umut bu yardımcı olur:

Kendinizi sadece yeni bir değişken bildirmek Bu yöntemi kullanmak için ve bu yüzden gibi anonim işlevi içinde kullanmaktan değere erişmek (o kadar da 'veya 'kendini' kullanmak yaygındır) .

Daha fazla açıklama için developer.mozilla.org adresinin good article describing the behavior of 'this' inside a functions scope vardır.

+0

Harika yanıt için teşekkürler! – user2924127

İlgili konular