Как создать новую наблюдаемую из результата другой наблюдаемой? - PullRequest
0 голосов
/ 11 ноября 2019

У меня есть функция, которая возвращает 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();
  }
....

Параметр загрузчика реализует вызов http изображения svg. Когда тема изменяется, вызывается функция 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>> insted of Observable<SafeHtml>. Так что, вероятно, мне следует обернуть результат наблюдаемой функции параметра загрузчика, но я не знаю, как это сделать.

Может ли кто-нибудь, кто имеет больше опыта, помочь мне в этом? Спасибо за ваше время и ответы.

Edit 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;
  }

Ответы [ 2 ]

1 голос
/ 12 ноября 2019

Вы можете просто перейти в обозреватель в своем загрузчике (). Подписаться, чтобы он работал

 try{
       loader().subscribe(observer)          
    }catch(err){
      observer.error(err);
    }
1 голос
/ 11 ноября 2019

Я не понимаю ваш вариант использования в достаточной степени, чтобы предоставить именно тот код, который вам нужен, но в целом, чтобы ответить на вопрос о том, как создать новую Observable из результата другой Observable, я использую код, подобный следующему:

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

Каждый раз, когда выбирается новый продукт, продукт попадает в поток this.selectedProduct$.

При этом используется forkJoin для создания нового наблюдаемого из списка поставщиков выбранного продукта, каждый получитодин через http.get и присоедините результат.

В общем, когда вам нужно создать Observable в другом Observable, вы хотите использовать оператор отображения более высокого порядка (например, switchMap, mergeMap или concatMap),Операторы отображения более высокого порядка обрабатывают подписки на внутренние наблюдаемые.

...