我创建了如下所示的通用数据服务:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { environment } from '../../../environments/environment';
import { Resource } from '../models/resource';
const API_URL = environment.apiUrl;
@Injectable()
export class DataService<T extends Resource> {
constructor(
private httpClient: HttpClient,
private endpoint: string) {}
public create(item: T): Observable<T> {
return this.httpClient
.post<T>(`${API_URL}/${this.endpoint}`, item);
}
public update(item: T): Observable<T> {
return this.httpClient
.put<T>(`${API_URL}/${this.endpoint}/${item.id}`, item);
}
read(id: number): Observable<T> {
return this.httpClient
.get(`${API_URL}/${this.endpoint}/${id}`)
.map(response => response as T);
}
list(): Observable<T[]> {
return this.httpClient
.get(`${API_URL}/${this.endpoint}`)
.map(response => response as T[]);
}
delete(id: number) {
return this.httpClient
.delete(`${API_URL}/${this.endpoint}/${id}`);
}
}
然后我创建了一个 CategoryService 来扩展此功能:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DataService } from './data.service';
import { Category } from '../models/category';
@Injectable()
export class CategoryService extends DataService<Category> {
constructor(httpClient: HttpClient) {
super(
httpClient,
'categories'
);
}
}
因此,现在我可以使用该服务的所有CRUD方法了。从那以后,我创建了许多其他服务,每个服务都扩展了DataService
。
问题是,我遇到了与返回类型不匹配的API端点。
例如,
端点“ / categories”,我的数据服务希望所有端点返回一个实体,该实体属于类别:
import { Resource } from "./resource";
export class Category extends Resource {
name: string
}
但是,类别API有一个端点,该端点返回问题的列表。该路径是“ / categories / 2 / questions”。 如何使它与我的通用数据服务一起使用? 我想答案是我不能,但是必须有一种解决方法,也许是在每次调用而不是实例化时提供模型类型?
任何帮助将不胜感激。 我希望这是有道理的。
答案 0 :(得分:1)
听起来这条新路线并不通用。我认为CategoryService
应该是实现新方法的类。
export class CategoryService extends DataService<Category> {
constructor(httpClient: HttpClient) {
super(
httpClient,
'categories'
);
}
getQuestions(id: number): Observable<Question[]> {
return this.httpClient
.get<Question[]>(`${API_URL}/${this.endpoint}/${id}/questions`);
}
}
您可以通过将其访问修饰符更改为endpoint
来获得对httpClient
和protected
的引用
答案 1 :(得分:0)
我决定删除通用服务,而改用通用方法。
因此,数据服务成为(请注意新的query
方法:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { environment } from '../../../environments/environment';
const API_URL = environment.apiUrl;
@Injectable()
export class DataService {
constructor(
private httpClient: HttpClient,
private endpoint: string) {}
create<T>(item: T): Observable<T> {
return this.httpClient
.post<T>(`${API_URL}/${this.endpoint}`, item);
}
update<T>(item: T): Observable<T> {
return this.httpClient
.put<T>(`${API_URL}/${this.endpoint}/${item.id}`, item);
}
read<T>(id: number): Observable<T> {
return this.httpClient
.get(`${API_URL}/${this.endpoint}/${id}`)
.map(response => response as T);
}
list<T>(): Observable<T[]> {
return this.httpClient
.get(`${API_URL}/${this.endpoint}`)
.map(response => response as T[]);
}
query<T>(path: string): Observable<T[]> {
return this.httpClient
.get(`${API_URL}/${this.endpoint}/${path}`)
.map(response => response as T[]);
}
delete(id: number) {
return this.httpClient
.delete(`${API_URL}/${this.endpoint}/${id}`);
}
}
我的类别服务变为:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DataService } from './data.service';
@Injectable()
export class CategoryService extends DataService {
constructor(httpClient: HttpClient) {
super(
httpClient,
'categories'
);
}
}
要获取我的“类别问题”,我可以这样做:
this.categoryService.query<Question>(`${this.category}/questions`);