Angular2组件的“ this”在执行回调函数时是未定义的

我有一个组件,它调用服务从 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
})
}
}
61673 次浏览

Use the Function.prototype.bind function:

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

What happens here is that you pass the gotMessages as a callback, when that is being executed the scope is different and so the this is not what you expected.
The bind function returns a new function that is bound to the this you defined.

You can, of course, use an arrow function there as well:

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

I prefer the bind syntax, but it's up to you.

A third option so to bind the method to begin with:

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

Or

export class MainComponent {
...


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


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

Because you're just passing the function reference in getMessages you don't have the right this context.

You can easily fix that by using a lambda which automatically binds the right this context for the use inside that anonymous function:

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

Please define function

gotMessages = (messagesFromApi) => {
messagesFromApi.forEach((m) => {
this.messages.push(m)
})
}

Or you can do it like this

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

I have same issue, resolved by using () => { } instead function()