Один наблюдаемый, несколько подписчиков Rxjs / угловой ресурс не работает - PullRequest
0 голосов
/ 07 мая 2018

Я использую angular 4 для одного из моих проектов, и я делаю http-вызов для получения данных. Я кеширую данные, когда данные возвращаются из бэкэнда, так что для последующих запросов мне не нужно делать повторные вызовы снова и снова.

getApplication(): Observable<Array<Application>> {
        return new Observable<Array<Application>>((observer) => {
            if (this.app&& this.app.length > 0) {
                observer.next(this.app)
            } else {
                this._http
                    .get<Application[]>(this.url)
                    .map((app) => this.mapToApp(app))
                    .subscribe((result: Array<Application>) => {
                        observer.next(result);
                    }, () => {
                        observer.next([]);
                    })
            }
        })
    }

Это прекрасно работает. Но если два вызова идут одновременно, я вижу, что на вкладке сети вместо одного идет два запроса. Поэтому я попытался с помощью share () удовлетворить «Один наблюдаемый, несколько подписчиков».

getApplication(): Observable<Array<Application>> {
            return new Observable<Array<Application>>((observer) => {
                if (this.app&& this.app.length > 0) {
                    observer.next(this.app)
                } else {
                    this._http
                        .get<Application[]>(this.url)
                        .map((app) => this.mapToApp(app))
                        .subscribe((result: Array<Application>) => {
                            observer.next(result);
                        }, () => {
                            observer.next([]);
                        })
                }
            }).share()
        }

Но это также, я вижу, что на вкладке сети вместо одного происходит несколько запросов. Что нужно сделать, чтобы сделать только один звонок и поделиться результатом со всеми абонентами? Пожалуйста помоги.

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Мое первое предложение - немного упростить код в этих строках

getApplication(): Observable<Array<Application>> {
      if (this.app && this.app.length > 0) {
         return Observable.of(this.app);
      }
      return this._http
                    .get<Application[]>(this.url)
                    .map((app) => this.mapToApp(app))
                    .do((result: Array<Application>) => {
                        this.app = result;
                    }
}

С помощью этой логики вы можете кэшировать, используя любую логику, какую захотите. Вы решили проверить, не является ли this.app ненулевым и имеет ли оно некоторые элементы. Но вы можете использовать любую другую логику, возможно, в зависимости от входных параметров.

Другая история - это проблема двух вызовов одновременно. В этом случае вы, вероятно, захотите как share Observable, чтобы была использована только одна подписка, так и replay последний зарегистрированный результат, чтобы вы могли вернуть кэшированное значение.

Один из способов сделать это может быть следующим

private cache$: Observable<Array<Application>>;

requestApplication(): Observable<Array<Application>> {
          return this._http
                        .get<Application[]>(this.url)
                        .map((app) => this.mapToApp(app))
                        .do((result: Array<Application>) => {
                            this.app = result;
                        }
}

getApplication() {
    if(!cache$) {
       cache$ = this.requestApplication().shareReplay(1);
    }
    return cache$;
}

Трюк здесь выполняется оператором shareReplay. Часть share обеспечивает совместное использование подписки. Часть replay с размером буфера 1 гарантирует, что последний сохраненный результат всегда будет возвращен.

Тогда вы можете время от времени сталкиваться с проблемой очистки кэша. Но здесь история усложняется, и я предлагаю вам взглянуть на эту очень хорошую статью https://blog.thoughtram.io/angular/2018/03/05/advanced-caching-with-rxjs.html

0 голосов
/ 07 мая 2018

Вы вызываете метод getApplication () дважды? Если да, то вы создаете две разные наблюдаемые.

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

...