打字稿:从抽象类

时间:2017-07-26 23:08:59

标签: angular typescript

做我们的第一个大应用程序我们遇到了一个应该在typescript 2.0 +

中修复的问题

拥有Abstract类:

export abstract class HttpBaseService {
  protected abstract readonly TAG: any;
  protected abstract _state: GlobalState;
  private r = Math.random();

  protected extractData(res: Response) {
    console.log(`${this.TAG}:extractData:`, res.json());
    const data = res.json() || [];
    return data;
  }

  protected handleErrors(error: Response) {
    console.error(`${this.TAG}:handleErrors:`, error);
    console.log(this.TAG);
    console.log(this._state);
    if (error.status === 401 || error.status === 403) {// Not Authorized
      console.error(`${this.TAG}:handleErrors: NOT AUTHORIZED`, error);
      this._state.notifyDataChanged("logout", error);
    }
    return Observable.throw(error.json());
  }

}

和实施:

@Injectable()
export class AlbumService extends HttpBaseService {
  TAG = AlbumService.name;

  constructor(protected _state: GlobalState,
              private http: Http,
              private auth: AuthService,
              private localStorage: LocalStorageService,) {
    super();
    this._state = _state;
  }

  albums() {
    console.log(`${this.TAG}:albums:`);
    console.log(this._state);
    const ALBUMS_URL = this.albumsUrl();
    const token = this.auth.getToken();
    const headers = new Headers();
    headers.append('Authorization', `Token ${token}`);

    return this.http
      .get(`${Constants.API_URL}${ALBUMS_URL}`, {headers})
      .catch(this.handleErrors)
      .map(this.extractData);
  }
}

当超类中的函数handleError在子类中执行时,参数TAG和_state都为"未定义"

请注意,我测试了它将它从构造函数中抽象,保护,公开,手动分配成员,以及其他几个。

我必须遗漏一些东西,因为在子类构造函数中,我尝试在分配_state之后调用handleError方法并且它按预期工作,具有TAG的值和_state的值。

更新:将问题减少到最小化

现在我有:

export abstract class HttpBaseService {
  protected abstract _state: GlobalState;

  protected handleErrors(error: Response) {
    console.log(this._state);
  }
  protected extractData(res: Response) {
    const data = res.json() || [];
    return data;
  }
}

和实施:

@Injectable()
export class AlbumService extends HttpBaseService {

  constructor(_state: GlobalState,
              private http: Http,
              private auth: AuthService,
              private localStorage: LocalStorageService,) {
    super();
    this._state = _state;
  }

  albums() {
    const token = this.auth.getToken();
    const headers = new Headers();
    headers.append('Authorization', `Token ${token}`);

    return this.http
      .get(`${Constants.API_URL}`, {headers})
      .catch(this.handleErrors)
      .map(this.extractData);
  }
}

2 个答案:

答案 0 :(得分:0)

  1. 从属性中删除abstract

    protected abstract readonly TAG: any;
    protected abstract _state: GlobalState;
    
  2. this._state = this._state应该是this._state = _state;

  3. AlbumService.name似乎没有在任何地方定义。
  4. 因此,您要将未定义 this._state分配给this._state,并将未定义,并指定underfined AlbumService.nameTAG

答案 1 :(得分:0)

我在这里找到答案:Angular 2 & RxJs catch function callback binding to 'this' causes http request to be repeated over and over

事实证明,当我将参考函数传递给.catch和.map时,这些函数被复制,并且" this"变化。

所以"这个"在Observable Subscriber的函数引用中。我不知道这是否是一个设计问题,但我花了一整天才弄明白。

所以,现在我在Super Class中的方法调用是这样的:

export abstract class HttpBaseService {
  protected readonly TAG = HttpBaseService.name;
  protected state: GlobalState;

  protected extractData(res: Response) {
    console.log(`${this.TAG}:extractData:`, res.json());
    const data = res.json() || [];
    return data;
  }

  protected handleErrors(error: Response) {
    console.error(`${this.TAG}:extractData:`, error);
    if (error.status === 401 || error.status === 403) {
      this.state.notifyDataChanged('logout', error);
    }
    return Observable.throw(error.json());
  }

}

我这样用过:

return this.http
  .delete(`${Constants.API_URL}${ALBUMS_URL}${id}/`, {headers})
  .catch((e, c) => this.handleErrors(e))
  .map(res => this.extractData(res));