【问题标题】:Angular2 use imported libs from base classAngular2 使用从基类导入的库
【发布时间】:2016-05-09 13:57:51
【问题描述】:

"angular2": "2.0.0-beta.17",

我希望能够在我的Base 中使用import { Http, Response } from 'angular2/http'; 并在子类中使用http

有没有办法做到这一点?

附:我不是在寻找“干净”的解决方案,欢迎使用黑客、变通方法和类似的东西

基类:

import { Http, Response } from 'angular2/http';

export class ServiceBase {
  constructor (private http: Http) {}

}

还有一个子类:

import { ApiServiceBase } from '../../api-service-base';
import { Injectable }     from 'angular2/core';
// import { Http, Response } from 'angular2/http';
import { AuthUser }       from './auth_user';
import { Observable }     from 'rxjs/Observable';
import { Headers, RequestOptions } from 'angular2/http';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class LoginService extends ApiServiceBase {
  constructor () {
    super();
  }
  private url = 'http://localhost:8080/api/signin';

  login (user: AuthUser): Promise<AuthUser> {
    let body = JSON.stringify(user);
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http.post(this.url, body, options)
               .toPromise()
               .then(this.extractData)
               .catch(this.handleError);
  }

  private extractData(res: Response) {
    console.log(res);
    if (res.status < 200 || res.status >= 300) {
      throw new Error('Bad response status: ' + res.status);
    }
    let body = res.json();
    return body.data || { };
  }

  private handleError (error: any) {
  }
}

【问题讨论】:

  • 为什么不想在子类中导入?
  • 但我想,你不关心“干净”的解决方案吗?这将比替代方案更“hacky”,不是吗?
  • 为了避免一行import 而添加所有这些额外的复杂性似乎是不必要的。实际上,您已经在子类中为 HeadersRequestOptions 导入了来自 angular2/http 的内容 - 为什么不直接添加 HttpResponse 呢?
  • 这不仅仅是一行,而是每个子服务的一行。当我想为我的所有child services添加一些东西时,这会派上用场

标签: typescript angular


【解决方案1】:

Angular2 不支持使用父类定义子类的依赖注入。

如果您想在父类中使用http 实例,您唯一可以在这里做的事情:

@Injectable()
export class LoginService extends ApiServiceBase {
  constructor (http:Http) {
    super(http);
  }

  (...)
}

编辑

解决方法包括定义一个自定义装饰器来设置依赖注入的元数据:

export function CustomInjectable(annotation: any) {
  return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('design:paramtypes', parentTarget);

    Reflect.defineMetadata('design:paramtypes', parentAnnotations, target);
  }
}

它将利用来自父构造函数的元数据,而不是它自己的。您可以在子类上使用它:

@Injectable()
export class BaseService {
  constructor(protected http:Http) {
  }
}

@CustomInjectable()
export class TestService extends BaseService {
  constructor() {
    super(arguments);
  }

  test() {
    console.log('http = '+this.http);
  }
}

看到这个 plunkr:https://plnkr.co/edit/DIMyUB6rCE5d78dPlPZB?p=preview

【讨论】:

  • 这就是为什么我正在寻找一个黑客来实现这一目标
  • 我正在寻找一种方法来避免子类中的import
  • 是否可以使用 grunt 或类似的东西来完成这项任务。就像某种预处理器一样,它将为我导入所有内容,因为 ts 必须转换为 ES5,所以应该可以在处理导入的转译过程中添加一个额外的步骤
  • 问题是Injectable装饰器实际上是基于子类的构造函数配置注入...
  • 一种方法是实现一个自定义装饰器,它查看父类而不是当前类来配置 DI。在这种情况下,您不需要在子类中定义构造函数。我实现了类似的东西,但对于组件。看到这个问题:stackoverflow.com/questions/36837421/…。也许可以做类似的事情......让我试一试;-)
猜你喜欢
  • 2017-02-13
  • 1970-01-01
  • 2012-01-09
  • 2016-04-19
  • 1970-01-01
  • 2016-08-01
  • 2016-11-06
  • 2018-04-10
  • 1970-01-01
相关资源
最近更新 更多