Typescript通用服务 [英] Typescript generic service

查看:107
本文介绍了Typescript通用服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对typescript和angular2 / 4很陌生,我正在构建一个包含Car和Driver两个基本实体的应用程序,我所做的就是使用API​​调用列出它们。



我面临的问题是每个CarService和DriverService都有代码冗余,并且我可能为其他实体服务使用相同的代码。

目前的实现跳过了其他的ilustration方法:

  @Injectable()
导出class CarService {

private actionUrl:string;
私人标题:标题;

构造函数(private _http:Http,private _configuration:Configuration){

//获取API URL并指定根
this.actionUrl = _configuration.serverWithApiUrl + '汽车/';

this.headers = new Headers();
this.headers.append('Content-Type','application / json');
this.headers.append('Accept','application / json');
}

//函数获取所有Cars - API CALL:/
public GetAll =():Observable< Car []> => ($ response)=>< Car []> response.json())
.catch (this.handleError);
}

//通过特定id获取汽车的功能 - API CALL:/:id
public GetSingle =(id:number):Observable< Car> => {
return this._http.get(this.actionUrl + id)
.map((response:Response)=>< Car> response.json())
.catch( this.handleError);
}

//添加一个Car-API的函数CALL:/ create
public Add =(newCar:Car):Observable< Car> => {
return this._http.post(this.actionUrl +'/ create',JSON.stringify(newCar),{headers:this.headers})
.catch(this.handleError);
}

//更新Car-API的函数CALL:/
public Update =(id:number,CarToUpdate:Car):Observable< Car> => {
return this._http.put(this.actionUrl + id,JSON.stringify(CarToUpdate),{headers:this.headers})
.catch(this.handleError);
}

//删除Car-API的函数CALL:/:id
public Delete =(id:number):Observable< Response> => {
return this._http.delete(this.actionUrl + id)
.catch(this.handleError);
}

//抛出错误的函数
private handleError(error:Response){
console.error(error);
return Observable.throw(error.json()。error ||'Server error');
}

只有DriverService改变的是 Car / 在url的结尾处和数据类型在 Observable< Car []> 和响应中。



我想知道什么是避免使用泛型服务的最佳方法,以及如何在Typescript中执行此操作。

解决方案

你可以创建一个抽象泛型类和两个继承自它的子类:



摘要class
$ b

export抽象类AbstractRestService< T> {
构造函数(protected _http:Http,protected actionUrl:string){
}

getAll():Observable< T []> {
返回this._http.get(this.actionUrl).map(resp => resp.json()as T []);
}
getOne(id:number):Observable< T> {
return this._http.get(`$ {this.actionUrl} $ {id}`).map(resp => resp.json()as T);


驱动程序服务等级

@Injectable()
export class DriverService extends AbstractRestService< Driver> {
构造函数(http:Http,configuration:Configuration){
super(http,configuration.serverWithApiUrl +Driver /);


汽车服务等级

@Injectable()
导出类CarService扩展了AbstractRestService< Car> {
构造函数(http:Http,configuration:Configuration){
super(http,configuration.serverWithApiUrl +Car /);


$ / code>

请注意,只有具体的类被标记为 @Injectable(),应该在模块内声明,而抽象的不应该。


I'm new to typescript and angular2/4 and I'm building a single app that have two basic entities which is Car and Driver and all I do is to list them with an API call.

The problem I'm facing is that I have code redundancy for each CarService and DriverService, and I might have the same code for other entities service.

The implementation is following so far, skipping other methods for ilustration :

@Injectable()
export class CarService  {

private actionUrl: string;
private headers: Headers;

constructor(private _http: Http, private _configuration: Configuration) {

    // Getting API URL and specify the root
    this.actionUrl = _configuration.serverWithApiUrl + 'Car/';

    this.headers = new Headers();
    this.headers.append('Content-Type', 'application/json');
    this.headers.append('Accept', 'application/json');
}

// Function to get all Cars - API CALL: /
public GetAll = (): Observable<Car[]> => {
    return this._http.get(this.actionUrl)
        .map((response: Response) => <Car[]>response.json())
        .catch(this.handleError);
}

// Function to get a Car by specific id - API CALL: /:id
public GetSingle = (id: number): Observable<Car> => {
    return this._http.get(this.actionUrl + id)
        .map((response: Response) => <Car>response.json())
        .catch(this.handleError);
}

// Function to add a Car - API CALL: /create
public Add = (newCar: Car): Observable<Car> => {
    return this._http.post(this.actionUrl + '/create', JSON.stringify(newCar), { headers: this.headers })
        .catch(this.handleError);
}

// Function to update a Car - API CALL: /
public Update = (id: number, CarToUpdate: Car): Observable<Car> => {
    return this._http.put(this.actionUrl + id, JSON.stringify(CarToUpdate), { headers: this.headers })
        .catch(this.handleError);
}

// Function to delete a Car - API CALL: /:id
public Delete = (id: number): Observable<Response> => {
    return this._http.delete(this.actionUrl + id)
        .catch(this.handleError);
}

// Function to throw errors
private handleError(error: Response) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
}

What only change with the DriverService is the Car/ at the end of the url and the data type in Observable<Car[]> and the response.

I would like to know what is the best way to avoid this with a generic service and how to do it in Typescript.

解决方案

You can create an abstract generic class and two children class that inherits from it :

abstract class:

export abstract class AbstractRestService<T> {
  constructor(protected _http: Http, protected actionUrl:string){
  }

  getAll():Observable<T[]> {
    return this._http.get(this.actionUrl).map(resp=>resp.json() as T[]);
  }
  getOne(id:number):Observable<T> {
    return this._http.get(`${this.actionUrl}${id}`).map(resp=>resp.json() as T);
  }
} 

driver service class

@Injectable()
export class DriverService extends AbstractRestService<Driver> {
  constructor(http:Http,configuration:Configuration){
    super(http,configuration.serverWithApiUrl+"Driver/");
  }
}

car service class

@Injectable()
export class CarService extends AbstractRestService<Car> {
  constructor(http:Http,configuration:Configuration) {
    super(http,configuration.serverWithApiUrl+"Car/");
  }
}

Note that only the concrete classes are marked as @Injectable() and should be declared inside a module while the abstract one should not.

这篇关于Typescript通用服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆