仅在不同可观察量的值为真而不是假后运行可观察量

  • 本文关键字:观察 运行 angular typescript rxjs
  • 更新时间 :
  • 英文 :


我正在用angular 12和rxjs编写一个类似电子商务的应用程序。

我创建了一个类别服务,从服务器中获取graphql类别并解析它们,因此它将很容易在网站的其余部分获得。

我遇到的问题是,如果用户立即进入一个使用类别服务的页面,那么它返回一个空响应,因为graphql还没有返回值。

所以我决定创建一个isinitialized可观察对象,并在它完成时将其设置为true,这样其他函数就知道它是可操作的

@Injectable({
providedIn: 'root'
})
export class ProductCategoriesService {
adminQueryProductCategories=this.gql.adminQueryProductCategories();
isInitialized: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(private gql: GraphqlService) {
this.adminQueryProductCategories.valueChanges.subscribe(({data})=>{
this.categories=data.adminQueryProductCategories;
this.parseCategoryTree(this.categories);
this.isInitialized.next(true);
});
}

现在这个函数从产品类别的可观察对象中获取数据:

getCategoryTitleByLabel(label: string): Observable<ProductCategory[]> {
return this.productCategories$.pipe(map((pc: ProductCategory[]) => pc.filter(p => p.category_label === label)));
}

我不知道如何实现这个可观察对象应该只有在isInitialized为真之后才执行

任何想法?

谢谢

一般来说,当用户浏览一个类别页面时,我想检查该类别是否存在,如果不存在,则将他路由到主页面。所以在第一次加载时,由于graphql请求没有完成,他总是被路由到主页面。

这是代码:

ngOnInit(): void {
this.route.params.subscribe(params => {
this.label = params['category'];
this.pcService.getCategoryTitleByLabel(this.label).subscribe((data)=>{
if (data.length !== 1) {
this.router.navigate(['/']).finally(()=>{
//TODO: popup of some sort ?
});
} else {

** update2 **

这是productCategories$的实现:

private productCategories = new BehaviorSubject<ProductCategory[]>([]);
get productCategories$(): Observable<ProductCategory[]> {
return this.productCategories;
}

**解决方案**

非常感谢你们的帮助。解决方案是简单地使用ReplaySubject,而不是@BizzyBob建议的BehaviorSubject。所以

不是

private productCategories = new BehaviorSubject<ProductCategory[]>([]);
get productCategories$(): Observable<ProductCategory[]> {
return this.productCategories;
}

productCategories$ = new ReplaySubject<ProductCategory[]>();

就是这样。问题解决:)get category by label函数保持不变:

getCategoryTitleByLabel(label: string): Observable<ProductCategory[]> {
return this.productCategories$.pipe(map((pc: ProductCategory[]) => pc.filter(p => p.category_label === label)));
}

您可以通过使用filterswitchMap来实现您正在寻找的内容,如下所示:

getCategoryTitleByLabel(label: string): Observable<ProductCategory[]> {
return this.isInitialized$.pipe(
filter(isInitialized => !!isInitialized),
switchMap(() => this.productCategories$),
map(pc => pc.filter(p => p.category_label === label))
);
}

但对我来说,真正的问题似乎是这句话:

它返回一个空响应,因为图形还没有返回值

this.productCategories$应该只发出有意义的数据,而不是"空响应"。除非"空";响应是有意义的,这似乎不是,它们应该在流的早期被过滤掉。如果是这种情况,您就不需要引入isInitialized$属性。

尝试如下:

getCategoryTitleByLabel(label: string): Observable<ProductCategory[]> {
return combineLatest({
pc: this.productCategories$,
init: this.isInitialized
}).pipe(
filter(({ init }) => !!init),
map(({ pc }) => pc.filter(p => p.category_label === label))
);
}

我的建议是订阅BehaviorSubject observable

你可以获取可观察对象的结果并执行一个操作:

this.isInitialized.subscribe((res) => {
if (res === true)
{
// do something, maybe set a flag etc.
}
});

最新更新