"This" komponentu Angular2 jest niezdefiniowany podczas wykonywania funkcji wywołania zwrotnego

Mam komponent, który wywołuje usługę w celu pobrania danych z RESTful endpoint. Ta usługa musi mieć funkcję wywołania zwrotnego do wykonania po pobraniu wspomnianych danych.

Problem polega na tym, że gdy próbuję użyć funkcji zwrotnej, aby dołączyć dane do istniejących danych w zmiennej komponentu, dostaję EXCEPTION: TypeError: Cannot read property 'messages' of undefined. Dlaczego this jest niezdefiniowany?

Wersja maszynopisu: Wersja 1.8.10

Kod kontrolera:

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
        })
    }
}
Author: Michael Gradek, 2016-07-07

5 answers

Użyj funkcji .prototyp.funkcja bind:

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

Dzieje się tak, że przekazujesz gotMessages jako wywołanie zwrotne, gdy jest ono wykonywane, zakres jest inny, więc this nie jest tym, czego oczekiwałeś.
Funkcja bind zwraca nową funkcję, która jest powiązana z this, którą zdefiniowałeś.

Możesz oczywiście użyć funkcji strzałki również tam:

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

Wolę składnię bind, ale to zależy od Ciebie.

Trzecia opcja więc aby związać metodę na początek:

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

Lub

export class MainComponent {
    ...

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

    getMessages(){
        this.apiService.getMessages(gotMessages);
    }
}
 166
Author: Nitzan Tomer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-30 08:10:24

Or you can do it like this

gotMessages(messagesFromApi){
    let that = this // somebody uses self 
    messagesFromApi.forEach((m) => {
        that.messages.push(m) // or self.messages.push(m) - if you used self
    })
}
 21
Author: Michal Kliment,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-20 20:55:12

Ponieważ przekazujesz odwołanie do funkcji w {[1] } nie masz odpowiedniego kontekstu this.

Można to łatwo naprawić, używając lambda, która automatycznie wiąże właściwy kontekst this do użycia wewnątrz tej anonimowej funkcji:

getMessages(){
    this.apiService.getMessages((data) => this.gotMessages(data));
}
 15
Author: rinukkusu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-07 12:29:28

Mam ten sam problem, rozwiązany za pomocą () => { } instead function()

 1
Author: Bharathiraja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-12 10:44:53

Proszę zdefiniować funkcję

gotMessages = (messagesFromApi) => {
  messagesFromApi.forEach((m) => {
    this.messages.push(m)
  })
}
 0
Author: Tài,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-15 02:34:15