如何根据另一个可观察结果创建新的可观察对象?

时间:2019-11-11 18:39:51

标签: javascript angular rxjs observable

我有一个函数,可以根据http请求返回一个Observable。我想在内存中为这些函数创建一个存储,但是当我调用一个存储时,我想针对该函数的原始上下文发出此存储的新结果。

就我而言,我有一个主题服务,该主题服务具有一个商店,一个relaod内容功能并注册新的加载器功能。

主题服务类

....
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调用。更改主题后,将调用reloadRegistratedContents函数,并在此处使用新的svg内容对视图进行修补。

我还有一个应该做魔术的烟斗:

@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函数的结果可以在开始时发出(下一个)svg,则每次调用reloadRegistratedContents时都会很好。另一方面,此代码返回类似:Observable<Observable<SafeHtml>>的{​​{1}}实例。因此,大概我应该包装可观察到的加载程序参数函数的结果,但我不知道该怎么做。

有更多经验的人可以帮助我吗? 谢谢您的时间和答复。

编辑1

我可以使其与Subject一起使用,但我认为这不是最佳实践:

Observable<SafeHtml>

2 个答案:

答案 0 :(得分:1)

我对您的用例不够了解,无法提供所需的确切代码,但是通常要回答如何根据另一个Observable的结果创建新的Observable的问题,我使用以下代码:

  selectedProductSuppliers$ = this.selectedProduct$
    .pipe(
      switchMap(selectedProduct =>
        forkJoin(selectedProduct.supplierIds.map(supplierId => this.http.get<Supplier>(`${this.suppliersUrl}/${supplierId}`)))
      )
    );

每次选择新产品时,该产品都会发送到this.selectedProduct$流中。

这使用forkJoin从所选产品的供应商列表中创建一个新的Observable,并通过http.get获得每个供应商并加入结果。

通常,每当需要在另一个Observable中创建一个Observable时,都希望使用更高阶的映射运算符(例如switchMap,mergeMap或concatMap)。高阶映射运算符处理对内部Observable的订阅。

答案 1 :(得分:1)

您只需在loader()中传递观察者即可。订阅使其生效

 try{
       loader().subscribe(observer)          
    }catch(err){
      observer.error(err);
    }