【问题标题】:Typescript: accessing public / protected members from abstract class打字稿:从抽象类访问公共/受保护成员
【发布时间】:2017-07-26 23:08:59
【问题描述】:

在做我们的第一个大型应用程序时,我们遇到了一个应该在 typescript 2.0+ 中修复的问题

拥有抽象类:

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);
  }
}

【问题讨论】:

  • 我不知道这是否与您遇到的问题有关,但 this._state = this._state; 看起来多余 - 应该是 this._state = _state; 吗?
  • @0mpurdy 这是我尝试的实现之一的错误
  • 已经试过不做抽象类了,不行
  • 我尝试了其他 9 种解决方案,包括非抽象扩展、超类中的构造函数、子类的构造函数中的赋值
  • 您是否尝试过将大部分代码删除到最低限度以重现问题?这将使回答更容易,并且在此过程中您可能会解决自己的问题! minimal reproducible example

标签: angular typescript


【解决方案1】:
  1. 从属性中删除abstract:

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

  3. AlbumService.name 似乎没有在任何地方定义。

因此,您将 undefined this._state 分配给 this._state,将其 undefined 分配,并将 underfined AlbumService.name 分配给 TAG。

【讨论】:

  • 已经试过了,在没有“abstract”关键字的情况下,我实际上将抽象放入属性中。
  • this._state = this._state 是其中一次的错误。我现在修好了。
  • AlbumService.name 是类的名称。它在子类中有效,但在调用超类中定义的方法时无效
【解决方案2】:

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

事实证明,当我将引用函数传递给 .catch 和 .map 时,这些函数被复制,“this”的含义发生了变化。

所以函数中的“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));

【讨论】:

    猜你喜欢
    • 2018-04-17
    • 1970-01-01
    • 2015-08-02
    • 2011-12-25
    • 2014-06-07
    • 1970-01-01
    • 2012-12-01
    • 2016-03-19
    • 2017-08-01
    相关资源
    最近更新 更多