У меня есть компонент, который вызывает службу для получения данных из конечной точки 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
})
}
}
javascript
arrays
typescript
angular
Майкл Градек
источник
источник
tsc -v
)Ответы:
Используйте функцию 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); } }
источник
Или вы можете сделать это так
gotMessages(messagesFromApi){ let that = this // somebody uses self messagesFromApi.forEach((m) => { that.messages.push(m) // or self.messages.push(m) - if you used self }) }
источник
Поскольку вы просто передаете ссылку на функцию, у
getMessages
вас нет правильногоthis
контекста.Вы можете легко исправить это, используя лямбду, которая автоматически связывает правильный
this
контекст для использования внутри этой анонимной функции:getMessages(){ this.apiService.getMessages((data) => this.gotMessages(data)); }
источник
У меня такая же проблема, которую можно решить, используя () => {} вместо function ()
источник
Пожалуйста, определите функцию
gotMessages = (messagesFromApi) => { messagesFromApi.forEach((m) => { this.messages.push(m) }) }
источник