Типовой сервис Typcript

Я новичок в машинописном и угловом2/4, и я создаю одно приложение с двумя базовыми объектами, которые являются Car and Driver, и все, что я делаю, - это перечислить их вызовом API.

Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть избыточность кода для каждого CarService и DriverService, и у меня может быть такой же код для службы других лиц.

Реализация продолжается до сих пор, пропуская другие методы для иллюстраций:

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

Единственное изменение с DriverService - это Car/ в конце URL-адреса и тип данных в Observable<Car[]> и ответ.

Я хотел бы знать, что лучший способ избежать этого с помощью общего сервиса и как это сделать в TypScript.

Ответ 1

Вы можете создать абстрактный общий класс и два дочерних класса, который наследует от него:

абстрактный класс:

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

класс обслуживания водителя

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

класс автосервиса

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

Обратите внимание, что только конкретные классы отмечены как @Injectable() и должны быть объявлены внутри модуля, а абстрактные - не должны.

Ответ 2

У вас есть базовый сервис для вашего приложения.

С get post и delete методы с вашей base URL прилагается.

export class HttpServiceBase {

    HOST_AND_ENDPOINT_START : string = 'you/rD/efa/ult/Url' ;
    public getWebServiceDataWithPartialEndpoint(remainingEndpoint: string): Observable<Response> {

        if (!remainingEndpoint) {
            console.error('HttpServiceBase::getWebServiceDataWithPartialEndpoint - The supplied remainingEndpoint was invalid');
            console.dir(remainingEndpoint);
        }

        console.log('GET from : ' , this.HOST_AND_ENDPOINT_START + remainingEndpoint);
        return this.http.get(
            this.HOST_AND_ENDPOINT_START + remainingEndpoint

        );
    }

Это полезная реализация, поскольку она позволяет вам легко отлаживать вызовы WS - все вызовы заканчиваются исходящими из базы.

HOST_AND_ENDPOINT_START может быть переопределен любым модулем, который вы хотите расширить базовую услугу.

Давайте сделаем вид, что ваша конечная точка - это что-то вроде: /myapp/rest/

И вы хотите реализовать HttpSearchBase вы можете просто расширить HttpServiceBase и переопределить HOST_AND_ENDPOINT_START с чем-то вроде:

/myapp/rest/search

Пример CarDriverService

@Injectable()
export class CarDriverService extends HttpServiceBase{

    //here we are requesting a different API
    HOST_AND_ENDPOINT_START : string = '/myapp/rest/vehicle/;
    getAllCars() : Observable<Car[]>{
    return this.getWebServiceDataWithPartialEndpoint('/Car')
           .map(res => <Car[]>res.json())
    }

    getAllDrivers(){
    return this.getWebServiceDataWithPartialEndpoint('/Driver')
    }

    addNewDriver(driver: Driver){
    return this.postWebServiceDataWithPartialEndpoint('/Driver/',driver)
    }


}