簡體   English   中英

如何從另一個 observable 的結果創建新的 observable?

[英]How to create new observable from the result of another observable?

我有一個 function 作為 http 請求的結果返回一個 Observable。 我想在 memory 中為這些函數創建一個存儲,但是當我調用一個存儲時,我想為該 function 的原始上下文發出新的結果。

在我的情況下,我有一個主題服務,它有一個商店,一個 relaod 內容 function 並注冊新的加載器 function。

主題服務class

....
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 function 將被調用,這里應該用新的 svg 內容修補視圖。

我還有一個 pipe 應該可以發揮作用:

@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 function 的結果可以在開始和每次調用 reloadRegistratedContents 時發出(下一個)svg,那就太好了。 另一方面,此代碼返回類似: Observable<Observable<SafeHtml>> of Observable<SafeHtml> 所以可能我應該包裝加載器參數函數的結果,但我不知道如何。

有更多經驗的人可以幫助我嗎? 感謝您的時間和回答。

編輯 1

我可以讓它與 Subject 一起工作,但我想這不是這里的最佳實踐:

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$ stream 中。

這使用forkJoin從所選產品的供應商列表中創建一個新的 Observable,通過http.get獲取每個並加入結果。

一般來說,每當您需要在另一個 Observable 中創建一個 Observable 時,您都希望使用更高階的映射運算符(例如 switchMap、mergeMap 或 concatMap)。 高階映射運算符處理對內部 Observable 的訂閱。

你可以在你的 loader().subscribe 中傳入觀察者,讓它工作

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM