Geri arama işlevi çalıştırılırken Angular2 bileşeninin "bu" tanımsız


94

RESTful bir uç noktadan veri almak için bir hizmeti çağıran bir bileşenim var. Bu hizmete, söz konusu veriler getirildikten sonra çalıştırılması için bir geri arama işlevi verilmesi gerekir.

Buradaki sorun, verileri bir bileşenin değişkenindeki mevcut verilere eklemek için geri arama işlevini kullanmayı denediğimde, bir EXCEPTION: TypeError: Cannot read property 'messages' of undefined. Neden thistanımsız?

TypeScript sürümü: Sürüm 1.8.10

Denetleyici kodu:

import {Component} from '@angular/core'
import {ApiService} from '...'

@Component({
    ...
})
export class MainComponent {

    private messages: Array<any>;

    constructor(private apiService: ApiService){}

    getMessages(){
        this.apiService.getMessages(gotMessages);
    }

    gotMessages(messagesFromApi){
        messagesFromApi.forEach((m) => {
            this.messages.push(m) // EXCEPTION: TypeError: Cannot read property 'messages' of undefined
        })
    }
}

TypeScript'in hangi sürümünü kullanıyorsunuz? ( tsc -v
İle

Bir istisna çünkü forEach. Bunun yerine For-of kullanın.
Pax Beach

Yanıtlar:


159

Function.prototype.bind işlevini kullanın :

getMessages() {
    this.apiService.getMessages(this.gotMessages.bind(this));
}

Burada olan şey, gotMessagesgeri arama olarak iletmenizdir, bu yürütülürken kapsam farklıdır ve bu nedenle thisbeklediğiniz gibi değildir. Fonksiyon bağlı yeni bir fonksiyon verir tanımladığınız.
bindthis

Elbette orada bir ok işlevi de kullanabilirsiniz:

getMessages() {
    this.apiService.getMessages(messages => this.gotMessages(messages));
}

bindSözdizimini tercih ederim ama bu size kalmış.

Başlamak için yöntemi bağlamak için üçüncü bir seçenek:

export class MainComponent {
    getMessages = () => {
        ...
    }
}

Veya

export class MainComponent {
    ...

    constructor(private apiService: ApiService) {
        this.getMessages = this.getMessages.bind(this);
    }

    getMessages(){
        this.apiService.getMessages(gotMessages);
    }
}

1
Çalıştı, teşekkürler! Ve bunun neden olduğunu açıkladığınız için teşekkürler.
Michael Gradek

Teşekkür ederim! OOP stilinin javascript özelliklerini sızdırması (bağlama) trajiktir.
skfd

21

Ya da böyle yapabilirsin

gotMessages(messagesFromApi){
    let that = this // somebody uses self 
    messagesFromApi.forEach((m) => {
        that.messages.push(m) // or self.messages.push(m) - if you used self
    })
}

13

Çünkü fonksiyon referansını iletiyorsunuz, getMessagesçünkü doğru thisbağlama sahip değilsiniz .

Bu thisanonim işlevin içinde kullanım için doğru bağlamı otomatik olarak bağlayan bir lambda kullanarak bunu kolayca düzeltebilirsiniz :

getMessages(){
    this.apiService.getMessages((data) => this.gotMessages(data));
}

İşte buydu! Teşekkürler
Michael Gradek

Mükemmel. En basit ve verimli çözüm.
Kon

1

Aynı sorunu yaşıyorum, bunun yerine function () kullanarak () => {} çözdüm


bu mevcut cevaplara herhangi bir bilgi eklemez
DerMike

0

Lütfen işlevi tanımlayın

gotMessages = (messagesFromApi) => {
  messagesFromApi.forEach((m) => {
    this.messages.push(m)
  })
}

bu mevcut cevaplara herhangi bir bilgi eklemez
DerMike
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.