J'ai un composant qui appelle un service pour extraire des données d'un noeud final RESTful. Ce service doit recevoir une fonction de rappel à exécuter après la récupération desdites données.
Le problème est que lorsque j'essaie d'utiliser la fonction de rappel pour ajouter les données aux données existantes dans la variable d'un composant, j'obtiens un EXCEPTION: TypeError: Cannot read property 'messages' of undefined
. Pourquoi this
est-il indéfini?
Version TypeScript: Version 1.8.10
Code du contrôleur:
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
})
}
}
Utilisez la fonction Function.prototype.bind :
getMessages() {
this.apiService.getMessages(this.gotMessages.bind(this));
}
Ce qui se passe ici, c’est que vous transmettez la gotMessages
en tant que rappel, lorsqu’elle est exécutée, la portée est différente et le this
n’est donc pas ce que vous attendiez.
La fonction bind
renvoie une nouvelle fonction liée à la this
que vous avez définie.
Vous pouvez bien sûr utiliser un fonction flèche là aussi:
getMessages() {
this.apiService.getMessages(messages => this.gotMessages(messages));
}
Je préfère la syntaxe bind
, mais c'est à vous de décider.
Une troisième option pour lier la méthode pour commencer:
export class MainComponent {
getMessages = () => {
...
}
}
Ou
export class MainComponent {
...
constructor(private apiService: ApiService) {
this.getMessages = this.getMessages.bind(this);
}
getMessages(){
this.apiService.getMessages(gotMessages);
}
}
Ou tu peux le faire comme ça
gotMessages(messagesFromApi){
let that = this // somebody uses self
messagesFromApi.forEach((m) => {
that.messages.Push(m) // or self.messages.Push(m) - if you used self
})
}
Parce que vous ne faites que passer la référence de fonction dans getMessages
, vous n'avez pas le bon contexte this
.
Vous pouvez facilement résoudre ce problème en utilisant un lambda qui lie automatiquement le bon contexte this
à l'usage de cette fonction anonyme:
getMessages(){
this.apiService.getMessages((data) => this.gotMessages(data));
}
S'il vous plaît définir la fonction
gotMessages = (messagesFromApi) => {
messagesFromApi.forEach((m) => {
this.messages.Push(m)
})
}