“This” del componente Angular2 non è definito quando si esegue la funzione di callback

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.

Il problema è quando provo ad usare la funzione di callback per aggiungere i dati ai dati esistenti nella variabile di un componente, ottengo EXCEPTION: TypeError: Cannot read property 'messages' of undefined . Perché this è indefinito?

Versione TypeScript: versione 1.8.10

Codice del controller:

 import {Component} from '@angular/core' import {ApiService} from '...' @Component({ ... }) export class MainComponent { private messages: Array; 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 }) } } 

Utilizzare la funzione Function.prototype.bind :

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

Quello che succede qui è che tu passi i gotMessages come callback, quando questo viene eseguito l’ambito è diverso e quindi this non è quello che ti aspettavi.
La funzione bind restituisce una nuova funzione che è vincasting a this hai definito.

Ovviamente puoi anche usare una funzione di freccia :

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

Preferisco la syntax di bind , ma dipende da te.

Una terza opzione per bind il metodo all’inizio:

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

O

 export class MainComponent { ... constructor(private apiService: ApiService) { this.getMessages = this.getMessages.bind(this); } getMessages(){ this.apiService.getMessages(gotMessages); } } 

O puoi farlo 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 }) } 

Poiché stai semplicemente passando il riferimento alla funzione in getMessages , non hai il diritto in this contesto.

Puoi facilmente risolverlo usando un lambda che lega automaticamente il diritto a this contesto per l’uso all’interno di quella funzione anonima:

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

Si prega di definire la funzione

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