javascript - 如何根据另一个可观察值的结果创建新的可观察值?

标签 javascript angular rxjs observable

我有一个函数,它返回一个 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/

相关文章:

javascript - 我的按钮在移动设备上不起作用,但在桌面设备上工作正常?

javascript结合多个正则表达式

angular - 用于可观察链接的仓促 forkjoin 替代 rxjs?

Angular 2 - 如何全局获取 Observable.throw

javascript - 如何在滑动 slider 中单击箭头1和滑动3时使slidesToScroll?

javascript - JavaScript 中的分页

javascript - Angular2错误: Return type of public method from exported class has or is using private name

angular - 获取组件中的路由参数

javascript - 为什么要切片不纯的管道?

angular - 如何通过单元测试覆盖 rxjs subscribe 方法?