2016-07-07 2 views
34

У меня есть компонент, который вызывает службу для извлечения данных из конечной точки RESTful. Эта услуга должна иметь функцию обратного вызова, которая должна выполняться после извлечения указанных данных.Компонент Angular2 «это» не определен при выполнении функции обратного вызова

Проблема заключается в том, что я пытаюсь использовать функцию обратного вызова для добавления данных к существующим данным в переменной компонента, я получаю EXCEPTION: TypeError: Cannot read property 'messages' of undefined. Почему this не определено? версия

Машинопись: Версия 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 
     }) 
    } 
} 
+0

Какая версия TypeScript вы используете? (Вы можете проверить это с помощью 'tsc -v') – rinukkusu

+0

Исключение, потому что forEach. Вместо этого используйте For-of. –

ответ

71

Используйте 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 =() => { 
     ... 
    } 
} 
+0

Работал, спасибо! И спасибо за объяснение, почему это происходит. –

+0

Сохранено мое время .... хорошее объяснение –

7

Потому что вы просто передав ссылку на функцию в getMessages вы не имеете право this контекст.

Вы можете легко исправить с помощью лямбды, который автоматически связывает правильный this контекст для использования внутри этой анонимной функции:

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

Вот оно! благодаря –

0

Уточнитните функцию

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

Или вы можете это сделать например

gotMessages(messagesFromApi){ 
    let that = this // somebody uses self 
    messagesFromApi.forEach((m) => { 
     that.messages.push(m) // or self.messages.push(m) - if you used self 
    }) 
} 
Смежные вопросы