Angular 使用数据服务集中数据和http调用
我已经阅读了很多关于如何使用http客户机在服务中实现http调用的教程,这很好。当我试图在两个不同的服务中分离数据和http调用时,问题就来了,我会因为可观察对象和订阅以及体系结构而感到困惑 请检查以下示例: 1 ListComponent-显示项目列表 1数据服务-用于数据,具有项目列表和获取、添加、更新、删除等功能。 1 HttpService-对于http调用,使用Swagger为Angular自动生成。 我使用DataService作为数据的中心点,以便可以从不同的组件访问数据。当ListComponent请求条目列表时,DataService调用http服务从服务器获取数据。http服务中的这个操作是异步的,因此它返回一个可观察的 我使用主题和订阅实现了它:Angular 使用数据服务集中数据和http调用,angular,Angular,我已经阅读了很多关于如何使用http客户机在服务中实现http调用的教程,这很好。当我试图在两个不同的服务中分离数据和http调用时,问题就来了,我会因为可观察对象和订阅以及体系结构而感到困惑 请检查以下示例: 1 ListComponent-显示项目列表 1数据服务-用于数据,具有项目列表和获取、添加、更新、删除等功能。 1 HttpService-对于http调用,使用Swagger为Angular自动生成。 我使用DataService作为数据的中心点,以便可以从不同的组件访问数据。当Li
export class ListComponent implements OnInit, OnDestroy {
private listChangedSubscription: Subscription;
ngOnInit() {
this.list = this.dataService.getList();
this.listChangedSubscription = this.dataService.listChangedSubject.subscribe(
(list: Array<Item>) => {
this.list = list;
});
ngOnDestroy() {
this.entriesChangedSubscription.unsubscribe();
}
export class DataService {
listChangedSubject = new Subject<Array<Item>>();
private list: Array<Item> = [];
private fetchItems() {
return this.httpService.getItems().subscribe(
(list: Array<Item>) => {
this.list= list;
this.listChangedSubject.next(this.list.slice());
}
);
}
export class HttpService {
public getItems(observe?: 'body', reportProgress?: boolean): Observable<Array<Item>>;
public getItems(observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<Item>>>;
public getItems(observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<Item>>>;
public getItems(observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
我认为在DataService中使用可观测值或承诺(而不是主题和订阅)可能是一种更好的方法,但我无法让它工作,对fetchData函数有什么建议吗
在所有教程中,我都阅读了直接调用http服务的组件,我认为这仅适用于组件保存其数据且不需要数据服务的简单场景
对此,建议采用什么方法
提前谢谢
Dani啊,好吧,我想我更能理解, 我认为实现这一点的最好方法仍然是主题数据服务。这就是RXJS最擅长的地方 列出组件模板:
<ul *ngFor="let item of list">
<li (click)="onClick(item)">
<span>{{ item.date } </span>
<span>{{ item.text }}</span>
</li>
</ul>
export class ListComponent implements OnInit {
list: Item[] = [];
ngOnInit() {
this.httpService.getItems().subscribe(val => {
this.list = val;
});
}
onClick(item: item): void {
this dataService.updateItemListSubject(item);
// navigate to route
}
}
请注意,您不再需要onDestroy和订阅列表。HttpClient将为您执行此操作
export class DataService {
private itemSubject = new Subject<Item>();
getItemSubject(): Observable<Item> {
return this.itemSubject.asObservable();
}
updateItemSubject(item: Observable<Item>): void {
this.itemSubject.next(item);
}
}
ItemDetail组件模板
<div>
{{item$ | async}}
</div>
export class ItemDetail implements OnInit {
item$: Observable<Item>
ngOnInit() {
this.item$ = this.dataService.getItemSubject();
}
}
export class HttpService {
// normal stuff
}
抱歉这么久了
让DataService进行Http调用可能会在将来的某个地方变得复杂,并且要求DataService了解更多关于应用程序的信息。这就是为什么我在父组件中进行Http调用,然后将响应分配给DataService中的一个值,如上所示
使用RXJS的优点是,无论您在哪里通过异步管道或订阅使用数据,每次发生更改时都会收到通知。它还可以防止您担心从DataService获取列表时意外地执行列表。2而且它会破坏一切,因为您忘记了列表到处都在使用。在Angular工作了几年后,我想我可以回答我自己的问题:- 我认为这可能是一个更好的方法,使用可观察到的或承诺 数据服务,而不是主题和订阅,但我没有 为了让它工作起来,对fetchData函数有什么建议吗 在Angular中,在服务中使用Subject是非常常见的,所以您可以发出值,客户端可以订阅。对于后者,通常会添加如下属性或方法:
const itemsSubject = new Subject<any>();
const items$ = itemsSubject.asObservable();
或
对于数据服务发出http请求的特定情况,可以使用Behavior Subject或ReplaySubject,以便在请求完成后订阅的客户端可以获得以前的响应
在所有教程中,我都阅读了直接调用
http服务,我认为它只对中的简单场景有效
该组件保存其数据,并且不需要数据
服务
对此,建议采用什么方法
角度组件的主要用途是处理视图的显示。一旦获取或处理数据变得复杂,强烈建议将其提取到服务中。这允许更好的组件重用性并提高可测试性
将此作为一般建议,并根据具体情况做出选择
这里有一个可以作为参考的帖子列表:
我还建议阅读Angular和RxJS的官方文档:
如果您编写自己的服务,而不是使用招摇过市或。您可以创建一个通用服务,并在类似于模型的项目上调用它,防止使用任何类型的服务来获得typescript和intellisense的功能。以下是一个例子: 服务:
@Injectable()
export class GenericService {
constructor(private _http: HttpClient) { }
get<T>(url: string): Observable<T> {
return this._http.get<T>(url);
}
post<T,U>(url: string, body: U): Observable<T> {
return this._http.post<T>(url, body);
}
put<T,U>(url: string, body: U): Observable<T> {
return this._http.put<T>(url, body);
}
delete<T>(url: string): Observable<T> {
return this._http.delete<T>(url);
}
}
组成部分
@Component({
selector: ''
...
providers: [GenericService]
})
export class ListComponent implements OnInit {
list: Item[] = [];
constructor(private _service: GenericService)
ngOnInit() {
this._service.get<Item>(url).subscribe(val => {
this.list = val;
}
}
}
通过使用这种方法,您可以删除您的服务文件,在需要调用api的地方,将通用服务注入组件并调用所需的http方法。通过在GenericService中调用httpClient方法上的toPromise,您可以将Observable转换为promise。我通常更喜欢使用能够访问数据的服务,而不是组件,因此它们之间更容易共享数据。例如,在此应用程序中,onClickitem导航到项目的详细信息,将项目的id作为route param:id传递。我需要在ItemDetail组件中获取此id的项目对象,以便在服务中而不是组件中拥有列表
耳鼻喉科使它更容易。我可以用@Input实现它,但它的元素更少。有什么建议吗?谢谢你的评论!该列表仅用于表示和选择:{{item.date}{{{item.text}}我更新了我的答案,以便更清楚地了解您试图做什么
@Component({
selector: ''
...
providers: [GenericService]
})
export class ListComponent implements OnInit {
list: Item[] = [];
constructor(private _service: GenericService)
ngOnInit() {
this._service.get<Item>(url).subscribe(val => {
this.list = val;
}
}
}