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


94

我有一个组件,该组件调用服务以从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
        })
    }
}

您正在使用哪个版本的TypeScript?(您可以通过进行检查tsc -v
rinukkusu 2016年

异常是因为forEach。改用For-of。
Pax海滩

Answers:


158

使用Function.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);
    }
}

1
工作,谢谢!感谢您解释为什么会这样。
Michael Gradek '16

谢谢!OOP风格泄漏javascript详细信息(绑定)的事实是可悲的。
skfd19年

21

或者你可以这样做

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

13

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

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

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

就是这样!谢谢
Michael Gradek '16

完善。最简单有效的解决方案。
Kon

1

我有同样的问题,可以使用()=> {}代替function()来解决


这不会在现有答案中添加任何信息
DerMike

0

请定义功能

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

这不会在现有答案中添加任何信息
DerMike
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.