web-dev-qa-db-fra.com

Le composant "this" du composant Angular2 n'est pas défini lors de l'exécution de la fonction de rappel

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
        })
    }
}
73
Michael Gradek

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);
    }
}
129
Nitzan Tomer

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
    })
}
18
Michal Kliment

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));
}
11
rinukkusu

S'il vous plaît définir la fonction

gotMessages = (messagesFromApi) => {
  messagesFromApi.forEach((m) => {
    this.messages.Push(m)
  })
}
0
Tài