2016-07-07 27 views
34

Ho un componente che chiama un servizio per recuperare i dati da un endpoint RESTful. Questo servizio deve essere dotato di una funzione di callback da eseguire dopo aver recuperato tali dati."Componente" del componente Angular2 non è definito quando si esegue la funzione di richiamata

Il problema è quando si tenta di utilizzare la funzione di richiamata per aggiungere i dati ai dati esistenti nella variabile di un componente, ottengo un EXCEPTION: TypeError: Cannot read property 'messages' of undefined. Perché è this indefinito? Versione

dattiloscritto: Versione 1.8.10

Controller cod:

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 
     }) 
    } 
} 
+0

Quale versione di TypeScript stai usando? (Puoi verificarlo con 'tsc -v') – rinukkusu

+0

Eccezione perché forEach. Usa invece For-of. –

risposta

71

Utilizzare la funzione Function.prototype.bind:

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

Quello che succede qui è che si passa il gotMessages come un callback, quando viene eseguito lo scope è diverso e quindi lo this non è quello che ti aspettavi.
La funzione bind restituisce una nuova funzione associata allo this definito dall'utente.

Ovviamente si può utilizzare una funzione di grasso freccia anche lì:

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

preferisco la sintassi bind, ma sta a voi.

Una terza opzione in modo di impegnare la modalità per cominciare:

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

Ha funzionato, grazie! E grazie per aver spiegato perché questo accade. –

+0

Salvato il mio tempo .... buona spiegazione –

7

Perché siete solo di passaggio il riferimento alla funzione in getMessages non si ha il diritto this contesto.

Si può facilmente risolvere che utilizzando un lambda che lega automaticamente il diritto this contesto per l'utilizzo all'interno di tale funzione anonima:

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

E 'stato! Grazie –

0

Si prega di definire funzione

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

Oppure si può fare In questo modo

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