1. ホーム
  2. javascript

[解決済み] Angular2コンポーネントのthisがコールバック関数実行時に未定義になる。

2022-10-29 02:11:23

質問

RESTfulエンドポイントからデータをフェッチするサービスを呼び出すコンポーネントがあります。このサービスは、前記データをフェッチした後に実行するコールバック関数を与えられる必要があります。

問題は、コンポーネントの変数にある既存のデータにデータを追加するためにコールバック関数を使用しようとすると EXCEPTION: TypeError: Cannot read property 'messages' of undefined . なぜ this は未定義なのでしょうか?

TypeScriptのバージョンです。バージョン1.8.10

コントローラのコードです。

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

どのように解決するのですか?

この場合 関数.prototype.bind 関数を使用します。

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

ここで起こることは gotMessages をコールバックとして渡すと、それが実行されるときにスコープが異なるので this は期待したものではありません。

bind 関数は、その関数にバインドされた新しい関数を返します。 this にバインドされた新しい関数を返します。

もちろん 矢印機能 を使うこともできます。

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

私は bind の構文が好きですが、それはあなた次第です。

第三の選択肢として、そもそもメソッドをバインドすることです。

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

または

export class MainComponent {
    ...

    constructor(private apiService: ApiService) {
        this.getMessages = this.getMessages.bind(this);
    }

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