2016-12-29 2 views
2

Я пытаюсь использовать наследование, чтобы сделать универсальный обработчик ошибок для моих сервисов, но по какой-то причине, когда он попадает в сам обработчик ошибок, «это» всегда кажется нулевым, и я не могу понять, почему. Я могу попасть в обработчик ошибок просто отлично, но я всегда получаю:angular2 service base class inheritance - почему это «это» null?

EXCEPTION: Uncaught (in promise): TypeError: Cannot read property 'http' of null

Любая идея, что я отсутствующий/делаю неправильно? Не знаете, как это может быть когда-либо?

Вот весь мой базовый класс для службы:

import { Injectable } from '@angular/core'; 
import { Http } from '@angular/http'; 

@Injectable() 
export class HttpServiceBase { 

    constructor(public http: Http) { 
     console.log('http', this.http); //just do this to prove that it is there - it is! 
    } 

    handleError(error: any): Promise<any> { 
     console.error('Application Error', error); //this logs fine 

     // TypeError: Cannot read property 'http' of null 
     this.http.get('/Account/IsLoggedIn') 
      .map(response => console.log('RESPONSE: ', response)); 

     return Promise.reject(error.message || error); 
    } 
} 

И это мой наследующий класс:

import 'rxjs/add/operator/toPromise'; 
import { Injectable } from '@angular/core'; 
import { Headers, Http } from '@angular/http'; 
import { HttpServiceBase } from './http-service.base'; 
import { Hero } from './hero'; 

@Injectable() 
export class HeroService extends HttpServiceBase { 

    private headers = new Headers({ 'Content-Type': 'application/json' }); 
    private heroesUrl = 'http://localhost:57569/Home/Heroes'; 

    constructor(http: Http) { super(http); } 

    getHeroes(): Promise<Hero[]> { 
     console.log('getting heroes'); 

     return this.http.get(this.heroesUrl + '-force-error') //so it will error out 
      .toPromise() 
      .then(response => response.json() as Hero[]) 
      .catch(this.handleError); 
    } 
} 

ответ

3

Для методов, которые должны использоваться как обратные вызовы, рекомендуется привязать их к контексту при построении. В машинописном это достижимо с помощью поля класса и стрелки методы:

constructor(public http: Http) {} 

handleError = (error: any): Promise<any> { ... } 

В отличии от связывания на вызове метода, это исключает возможность неправильного контекста.

Более предпочтительный способ может быть:

constructor(public http: Http) { 
    this.handleError = this.handleError.bind(this); 
} 

handleError(error: any): Promise<any> { ... } 

Он делает то же самое, но имеет более проверяемость, потому что она позволяет шпионить/макет HttpServiceBase.prototype.handleError до создания экземпляра класса.

+0

Все правильные ответы, но это было самое полное! Большое спасибо! – naspinski

+0

Конечно, пожалуйста. – estus

2

Любого шанс это фиксирует это?

.catch(this.handleError.bind(this)); 
4

Это происходит потому, что вы передаете в HandleError как функция к функции улова. И когда он называется, у него будет другой этот объект.

Вы можете передать функцию стрелки в catch сохранить тот же контекст.

.catch(error => this.handleError(error)); 

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

Смежные вопросы