J'ai un composant qui appelle un service pour récupérer des données à partir d'un point final REST. Ce service doit recevoir une fonction de rappel pour l'exécution après avoir récupéré ces données.
Le problème est quand 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 une EXCEPTION: TypeError: Cannot read property 'messages' of undefined
. Pourquoi est- this
indéfini?
Version TypeScript: version 1.8.10
Code de 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 les informations gotMessages
tant que rappel, lorsque cela est en cours d'exécution, la portée est différente et donc this
n'est pas ce que vous attendiez.
La fonction bind
renvoie une nouvelle fonction qui est liée à this
vous avez définie.
Vous pouvez bien sûr utiliser une fonction de flèche en gras aussi:
getMessages() { this.apiService.getMessages(messages => this.gotMessages(messages)); }
Je préfère la syntaxe de bind
, mais c'est à vous de décider.
Une troisième option pour lier la méthode pour commencer:
export class MainComponent { getMessages = () => { ... } }
Parce que vous passez simplement la référence de la fonction dans getMessages
vous n'avez pas le droit sur this
contexte.
Vous pouvez facilement réparer cela en utilisant un lambda qui lie automatiquement le droit à this
contexte pour l'utilisation à l'intérieur de cette fonction anonyme:
getMessages(){ this.apiService.getMessages((data) => this.gotMessages(data)); }
Ou vous pouvez 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 }) }
Définissez la fonction
gotMessages = (messagesFromApi) => { messagesFromApi.forEach((m) => { this.messages.push(m) }) }