我有两个同级组件,它们需要访问在可观察对象中检索的数据,该可观察对象是在基于用户输入可观察对象的服务中动态创建的。我正在努力理解如何让 search-list
组件监听由 search
组件创建的可观察对象。我是否应该将服务创建的最后一个搜索可观察值存储为搜索服务中的另一个可观察值,是否应该将搜索可观察值存储在 search
组件中并通过引用进行访问,还是应该在搜索后发出数据观察者在 search
组件中完成?
search.service.ts
export interface SearchApi {
data: string[]
}
export class SearchService {
loading: EventEmitter<boolean> = new EventEmitter();
constructor(private httpClient: HttpClient) {
}
search(terms: Observable<string>){
return terms.pipe(debounceTime(400))
.pipe(distinctUntilChanged())
.pipe(switchMap(term => {
this.loading.emit(true);
return this.searchEntries(term);
}))
.pipe((data) => {
this.loading.emit(false);
return data;
});
}
searchEntries(term){
return this.httpClient.post<SearchApi>(this.baseUrl,term);
}
}
search.component.ts
import { Subject, Observable } from 'rxjs';
export class SearchComponent implements OnInit {
searchTerm$ = new Subject<string>();
constructor(private searchService: SearchService) {
searchService.loading.subscribe(isLoading => {
console.log(`Is loading: ${isLoading}`);
});
searchService.search(this.searchTerm$).subscribe(results => {
console.log(`Search results ${results}`);
});
}
}
search-list.component.ts
export class SearchListComponent implements OnInit {
constructor(private searchService: SearchService) {
searchService.loading.subscribe(isLoading => {
console.log(`Is loading: ${isLoading}`);
});
/* Not sure how I would subscribe to observable that search.service.ts created */
/*
searchService.search().subscribe(results => {
console.log(`Search results ${results}`);
});
*/
}
}
最佳答案
只需使用主题来共享状态并将“加载状态”操作与“接收状态”操作分开。
export class SearchService {
private loading: Subject<boolean> = new Subject(); // use subjects, keep them private
loading$: Observable<boolean> = this.loading.asObservable(); // public observable
private searchResults = new BehaviorSubject(null); // BehaviorSubjects solve timing problems
searchResults$ = this.searchResults.asObservable();
constructor(private httpClient: HttpClient) {
}
search(terms: Observable<string>){
return terms.pipe(
debounceTime(400), // cleaner syntax / less pipes
distinctUntilChanged(),
tap(v => this.loading.next(true)), // subjectsuse next, use tap for side effects
switchMap(term => this.searchEntries(term)),
tap(v => this.loading.next(false)) // use tap for side effects
).subscribe(this.searchResults); // send it to the subject
}
searchEntries(term){
return this.httpClient.post<SearchApi>(this.baseUrl,term);
}
}
然后在您的组件中,您订阅 searchResults$ 并在想要填充搜索结果时调用 search() 。
搜索.component.ts
import { Subject, Observable } from 'rxjs';
export class SearchComponent implements OnInit {
searchTerm$ = new Subject<string>();
constructor(private searchService: SearchService) {
searchService.loading$.subscribe(isLoading => {
console.log(`Is loading: ${isLoading}`);
});
searchService.search(this.searchTerm$); // call the state load action
}
}
搜索列表.component.ts
export class SearchListComponent implements OnInit {
constructor(private searchService: SearchService) {
searchService.loading$.subscribe(isLoading => {
console.log(`Is loading: ${isLoading}`);
});
searchService.searchResults$.subscribe(results => { // receive state here
console.log(`Search results ${results}`);
});
}
}
关于angular - 在组件之间共享动态创建的 observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54915871/