从 Observable 发出,然后进行额外的 REST API 调用以获得更多细节
Emit from Observable and then make additional REST API call for more detail
我有两种方法可以对 Rest API 进行 HTTP 调用。一个是 getProducts() ,它将 return 一个产品数组,另一个是 getProductsDetail() ,它可以将该数组作为参数,并将 return 填充了附加字段的产品数组。
我想按顺序调用这两个 API,getProductsDetail() 取决于 getProducts() 的结果,但我希望我的 Observable 在 getProducts() 准备就绪后立即发出结果。然后在调用 returns.
时让 getProductsDetail() 发出额外的细节
有没有办法用像 concatMap 或 mergeMap 这样的 RxJS 运算符来做到这一点?我想让我的模板尽快开始显示,但请在可用时填写额外的数据
更新:
您好,感谢您的回复!抱歉,我目前只是伪代码,但我认为我最初的尝试将类似于 Authur 下面的内容
initProductsPage(): Observable<Products[]>{
this.productsService.getProducts().pipe(
switchMap(
(products: Products[]) => {
// would like to also emit products here
return this.productsService.getProductsDetail(products);
}
)
}
我的理解是,在这种情况下,initProductsPage() 的订阅者只会在 getProductsDetail() returns 时收到输出。我想让该订户在执行 getProductsDetails() 时获得产品。
假设 getProducts()
和 getProductsDetail()
return 和 Observable<Product[]>
,你可以这样做:
getProductsWithDetailsHydration(): Observable<Product[]> {
const productsShared$ = this.getProducts().pipe(share()); // <- to share same GET products request.
return merge(
productsShared$, // <- 1st obs Gets and emits Products
productsShared$.pipe( //<- 2nd obs Gets details using products response and emit Products with Details
concatMap((products) => this.getProductsDetail(products))
)
);
}
干杯
从 API 开始的另一种方法是使用 getProductDetail$() 方法。其中可以获得单个产品的详细信息。然后您可以轻松地在模板本身中使用 async
并填充模板。
示例模板代码
<ng-container *ngIf="getProduct$() | async as product">
// Some info on product
<div>{{product.title}}</div>
<ng-container *ngIf="getProductDetail$(product.id) | async as productDetail">
// Some info on product details
<div>{{productDetail.description}}</div>
</ng-container>
</ng-container>
我认为解决这个问题的更好方法是将两个 observable 分开。
然后您可以订阅并获取值:
// Class variables
products: Products[];
products$: Observable<Products[]>;
productsDetails: ProductsDetails[];
productsDetails$: Observable<ProductsDetails[]>;
// Call OnInit or OnChanges depending of your needs
initProductsPage(): void {
// Initialize the observables
this.products$ = this.productsService.getProducts();
this.productsDetails$ = this.products$.pipe(
switchMap((products) => this.getProductsDetail(products))
);
// Using take(1) to complete the observable after it gets the value
this.products$.pipe(take(1)).subscribe(products => {
this.products = products;
});
// Using take(1) to complete the observable after it gets the value
this.productsDetails$.pipe(take(1)).subscribe(productsDetails => {
this.productsDetails = productsDetails;
});
}
然后您可以在模板中使用 products
和 productsDetails
。
您也可以直接在带有 |async
的模板上使用可观察对象,在这种情况下,initProductsPage()
的第二部分将不是必需的。
// Class variables
products: Products[];
products$: Observable<Products[]>;
productsDetails: ProductsDetails[];
productsDetails$: Observable<ProductsDetails[]>;
// Call OnInit or OnChanges depending of your needs
initProductsPage(): void {
// Initialize the observables
this.products$ = this.productsService.getProducts();
this.productsDetails$ = this.products$.pipe(
switchMap((products) => this.getProductsDetail(products))
);
}
我有两种方法可以对 Rest API 进行 HTTP 调用。一个是 getProducts() ,它将 return 一个产品数组,另一个是 getProductsDetail() ,它可以将该数组作为参数,并将 return 填充了附加字段的产品数组。
我想按顺序调用这两个 API,getProductsDetail() 取决于 getProducts() 的结果,但我希望我的 Observable 在 getProducts() 准备就绪后立即发出结果。然后在调用 returns.
时让 getProductsDetail() 发出额外的细节有没有办法用像 concatMap 或 mergeMap 这样的 RxJS 运算符来做到这一点?我想让我的模板尽快开始显示,但请在可用时填写额外的数据
更新:
您好,感谢您的回复!抱歉,我目前只是伪代码,但我认为我最初的尝试将类似于 Authur 下面的内容
initProductsPage(): Observable<Products[]>{
this.productsService.getProducts().pipe(
switchMap(
(products: Products[]) => {
// would like to also emit products here
return this.productsService.getProductsDetail(products);
}
)
}
我的理解是,在这种情况下,initProductsPage() 的订阅者只会在 getProductsDetail() returns 时收到输出。我想让该订户在执行 getProductsDetails() 时获得产品。
假设 getProducts()
和 getProductsDetail()
return 和 Observable<Product[]>
,你可以这样做:
getProductsWithDetailsHydration(): Observable<Product[]> {
const productsShared$ = this.getProducts().pipe(share()); // <- to share same GET products request.
return merge(
productsShared$, // <- 1st obs Gets and emits Products
productsShared$.pipe( //<- 2nd obs Gets details using products response and emit Products with Details
concatMap((products) => this.getProductsDetail(products))
)
);
}
干杯
从 API 开始的另一种方法是使用 getProductDetail$() 方法。其中可以获得单个产品的详细信息。然后您可以轻松地在模板本身中使用 async
并填充模板。
示例模板代码
<ng-container *ngIf="getProduct$() | async as product">
// Some info on product
<div>{{product.title}}</div>
<ng-container *ngIf="getProductDetail$(product.id) | async as productDetail">
// Some info on product details
<div>{{productDetail.description}}</div>
</ng-container>
</ng-container>
我认为解决这个问题的更好方法是将两个 observable 分开。
然后您可以订阅并获取值:
// Class variables
products: Products[];
products$: Observable<Products[]>;
productsDetails: ProductsDetails[];
productsDetails$: Observable<ProductsDetails[]>;
// Call OnInit or OnChanges depending of your needs
initProductsPage(): void {
// Initialize the observables
this.products$ = this.productsService.getProducts();
this.productsDetails$ = this.products$.pipe(
switchMap((products) => this.getProductsDetail(products))
);
// Using take(1) to complete the observable after it gets the value
this.products$.pipe(take(1)).subscribe(products => {
this.products = products;
});
// Using take(1) to complete the observable after it gets the value
this.productsDetails$.pipe(take(1)).subscribe(productsDetails => {
this.productsDetails = productsDetails;
});
}
然后您可以在模板中使用 products
和 productsDetails
。
您也可以直接在带有 |async
的模板上使用可观察对象,在这种情况下,initProductsPage()
的第二部分将不是必需的。
// Class variables
products: Products[];
products$: Observable<Products[]>;
productsDetails: ProductsDetails[];
productsDetails$: Observable<ProductsDetails[]>;
// Call OnInit or OnChanges depending of your needs
initProductsPage(): void {
// Initialize the observables
this.products$ = this.productsService.getProducts();
this.productsDetails$ = this.products$.pipe(
switchMap((products) => this.getProductsDetail(products))
);
}