我有一个函数,它返回一个 Observable 作为 http 请求的结果。我想在内存中为这些函数创建一个存储,但是当我调用一个函数时,我想为该函数的原始上下文发出新的结果。
就我而言,我有一个主题服务,其中有一个商店、一个重新加载内容功能和注册新的加载程序功能。
主题服务类
....
contentLoaderRegistry = [];
public reloadRegistratedContents(){
this.contentLoaderRegistry.forEach((loader) => {
loader();
});
}
public registerThemeDependentContentLoader(loader:()=>Observable<SafeHtml>):Observable<SafeHtml>{
const loaderWrapper:() => Observable<SafeHtml> = ():Observable<SafeHtml> => {
return Observable.create((observer) => {
try{
observer.next( ...??? loader());
}catch(err){
observer.error(err);
}
return () => {
//observer.complete();
};
});
};
this.contentLoaderRegistry.push(loaderWrapper);
return loaderWrapper();
}
....
loader参数正在实现svg图像的http调用。当主题更改时,将调用 reloadRegisteratedContents 函数,并且此处应使用新的 svg 内容修补 View 。
我还有一个可以发挥魔力的管道:
@Pipe({
name: 'themeDependentContent'
})
export class ThemeDependentContentPipe implements PipeTransform {
constructor(
private _theme:ThemeService,
private _http:HttpClient,
private _sanitizer:DomSanitizer
){}
transform(url:string):Observable<SafeHtml> {
let themeDependentContentLoader:()=>Observable<SafeHtml> = () => {
return this._http.get(url, {headers: new HttpHeaders().set('Content-Type', 'image/svg+xml'), responseType: 'text'}).pipe(map<string, SafeStyle>((svg:string) => {
return this._sanitizer.bypassSecurityTrustHtml(svg);
}));
}
return this._theme.registerThemeDependentContentLoader(themeDependentContentLoader);
}
}
如果registerThemeDependentContentLoader函数的结果可以在开始时和每次调用reloadRegisteratedContents时发出(接下来)svg,那就太好了。另一方面,此代码返回类似:Observable<Observable<SafeHtml>>
安装了Observable<SafeHtml>
。所以我可能应该包装加载器参数函数的可观察结果,但我不知道该怎么做。
有经验的人可以帮我解决这个问题吗? 感谢您的宝贵时间和答复。
编辑 1
我可以让它与主题一起工作,但我想这不是最佳实践:
public registerThemeDependentContentLoader(loader:()=>Observable<SafeHtml>):Observable<SafeHtml>{
let observer = new Subject<SafeHtml>();
const loaderWrapper = () => {
loader().subscribe((svg) => {
observer.next(svg);
}, (err) => {
observer.error(err);
});
}
this.contentLoaderRegistry.push(loaderWrapper);
return observer;
}
最佳答案
我不太了解你的用例,无法提供你需要的确切代码,但为了一般性地回答如何从另一个 Observable 的结果创建一个新的 Observable 的问题,我使用如下代码:
selectedProductSuppliers$ = this.selectedProduct$
.pipe(
switchMap(selectedProduct =>
forkJoin(selectedProduct.supplierIds.map(supplierId => this.http.get<Supplier>(`${this.suppliersUrl}/${supplierId}`)))
)
);
每次选择新产品时,该产品都会发送到 this.selectedProduct$
流中。
这使用forkJoin
从所选产品的 vendor 列表中创建一个新的Observable,通过http.get
获取每个并加入结果。
一般来说,每当您需要在另一个 Observable 中创建一个 Observable 时,您都需要使用高阶映射运算符(例如 switchMap、mergeMap 或 concatMap)。高阶映射运算符处理对内部 Observables 的订阅。
关于javascript - 如何根据另一个可观察值的结果创建新的可观察值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58806929/