执行回调函数时,Angular2组件的"this"未定义

Mic*_*dek 76 javascript arrays typescript angular

我有一个组件调用服务从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
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

Nit*_*mer 136

使用Function.prototype.bind函数:

getMessages() {
    this.apiService.getMessages(this.gotMessages.bind(this));
}
Run Code Online (Sandbox Code Playgroud)

这里发生的是你gotMessages作为一个回调传递,当执行它时,范围是不同的,所以这this不是你所期望的.
bind函数返回一个绑定到this您定义的新函数.

当然,您也可以使用箭头功能:

getMessages() {
    this.apiService.getMessages(messages => this.gotMessages(messages));
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢bind语法,但这取决于你.

第三个选项,以便绑定方法开始:

export class MainComponent {
    getMessages = () => {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

export class MainComponent {
    ...

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

    getMessages(){
        this.apiService.getMessages(gotMessages);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ent 18

或者你可以这样做

gotMessages(messagesFromApi){
    let that = this // somebody uses self 
    messagesFromApi.forEach((m) => {
        that.messages.push(m) // or self.messages.push(m) - if you used self
    })
}
Run Code Online (Sandbox Code Playgroud)


rin*_*usu 12

因为您只是传递函数引用,getMessages所以没有正确的this上下文.

您可以通过使用lambda轻松解决这个问题,该lambda会自动绑定正确的this上下文以供匿名函数使用:

getMessages(){
    this.apiService.getMessages((data) => this.gotMessages(data));
}
Run Code Online (Sandbox Code Playgroud)