在问这个问题之前,我在这里进行了一些研究,只发现人们询问将搜索值传递给其他API并取回结果。我的问题完全不同。我有两个组件和一个服务:
时刻都需要保留原始应用列表的副本以进行过滤。
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, distinctUntilChanged, filter } from 'rxjs/operators';
import { Observable, BehaviorSubject } from 'rxjs';
import { Application } from '../models/apps.model';
@Injectable({
providedIn: 'root'
})
export class AppsService {
private appListSubject: BehaviorSubject<Application[]>;
private filteredAppListSubject: BehaviorSubject<Application[]>;
private appList: Observable<Application[]>;
constructor(private httpClient: HttpClient) {
this.appListSubject = new BehaviorSubject<Application[]>({} as Application[]);
this.filteredAppListSubject = new BehaviorSubject<Application[]>({} as Application[]);
this.appList = this.filteredAppListSubject.asObservable().pipe(distinctUntilChanged());
}
getApps(): Observable<Application[]> {
return this.httpClient.get('http://localhost:3000/api/user/apps').pipe(map(
(res: any) => {
this.setAppList = res;
return res;
}
));
}
public get getCurrentAppList() {
return this.appList;
}
public set setAppList(apps: Application[]) {
this.appListSubject.next(apps);
this.filteredAppListSubject.next(apps);
}
public searchApp(searchTerm: string) {
const filteredApps = this.appListSubject.pipe(filter(
(app: any) => {
if (app.name.includes(searchTerm)) {
return app;
}
}
));
this.filteredAppListSubject.next(filteredApps);
}
}
这是我当前对应用程序服务的实现。
我的目标是让applist组件订阅appList,每当搜索栏组件要求服务寻找值时,applist组件都会从可观察对象中获取新的一组应用程序。
现在,由于管道函数返回了一个可观察的对象,因此我无法将结果添加为行为主体的下一个值。
我也希望您对此特定实施有意见。谢谢!
我认为您的设计使问题看起来比实际的更加复杂。
数据流是一种方式:
HeaderComponent
-searchTerm
-> AppService
-apps
-> AppListComponent
我认为您只需要Subject
中的AppService
作为代理即可。 HeaderComponent
将向其中传递搜索词,AppListComponent
将接收搜索结果。
app.service.ts
@Injectable({ providedIn: 'root' })
export class AppService {
private apps: Application[];
private filteredApps$: Subject<Application[]> =
new ReplaySubject<Application[]>(1);
getSearchResults(): Observable<Application[]> {
return this.filteredApps$.asObservable();
}
search(searchTerm: string): Observable<void> {
return this.fetchApps().pipe(
tap((apps: Application[]) => {
apps = apps.filter(app => app.name.toLowerCase().includes(searchTerm));
this.filteredApps$.next(apps);
}),
map(() => void 0)
);
}
private fetchApps(): Observable<Application[]> {
// return cached apps
if (this.apps) {
return of(this.apps);
}
// fetch and cache apps
return this.httpClient.get('http://localhost:3000/api/user/apps').pipe(
tap((apps: Application[]) => this.apps = apps)
);
}
}
应用程序服务将在首次搜索时缓存http响应。当搜索词进入服务时,它将获取应用程序,对其进行过滤并通过主题发布它们。列出搜索结果的组件将订阅该主题。
header.component.ts
constructor(private appService: AppService) {
}
searchTerm = '';
ngOnInit() {
this.appService.search(this.searchTerm).subscribe();
}
onSearchTermChange(): void {
this.appService.search(this.searchTerm).subscribe();
}
header.component.html
<input [(ngModel)]="searchTerm" (ngModelChange)="onSearchTermChange()" />
app-list.component.ts
constructor(private appService: AppService) {
}
apps$: Observable<Application[]> = this.appService.getSearchResults();
app-list.component.html
<div *ngFor="let app of apps$ | async">
{{app.name}}
</div>