ReplySubject превращает весь комбайнПоследний горячий - PullRequest
0 голосов
/ 06 июня 2019

Live: https://stackblitz.com/edit/rxjs-6aikyy?file=index.ts

const sub = new ReplaySubject(1);
const source = combineLatest(
  of('World'),
  sub,
).pipe(
  map(([, n]) => n) ,
  tap(x => console.log('Tap', x)),
  publishReplay(1),
  refCount(),
);

sub.next(1);

const subscription = source.subscribe(x => console.log('Sub', x));
sub.next(2);

subscription.unsubscribe();
sub.next(3);

console.log('pause');
sub.next(4);

source.subscribe(x => console.log('Sub', x));


/**
 * Tap 1 (unwanted)
 * Sub 1 (unwanted)
 * Tap 2
 * Sub 2
 * pause
 * Sub 2 (why exaclty does this happened?)
 * Tap 4
 * Sub 4
 */

Это немного упрощено, но хорошо показывает мою проблему.В моем реальном коде я объединяю 1 BehaviourSubject и 2 ReplySubject с, затем перенаправляю его в switchMap и извлекаю данные с сервера.Я действительно не хочу продолжать делать HTTP-вызовы, если кто-то на самом деле не слушает.

Кто-то знает, почему я получаю первое уведомление от ReplaySubject (Tap 1 & Sub 1), а также почему "Sub 2"появляется после паузы?


Фактический контрольный пример

this.currentPage = new BehaviourSubject(1);
// Internal
const folderIDAndPage: Observable<[string, number]> = combineLatest(
  /** Angular's BehaviourSubject of URL maped to id */
  activatedRoute.url.pipe(
    switchMap(segments => folderService.getFoldersFromSegments(segments)),
    distinctUntilChanged(),
  ),
  /** BehaviourSubject/ReplaySubject (either) of QueryString maped to page */
  this.currentPage.pipe(
    distinctUntilChanged(),
  ),
).pipe(
  // Prevent repeating HTTP somehow...
);

// Public
this.folders = folderIDAndPage.pipe(
  switchMap(([folderID, page]) => folderService.getFfolders(folderID, page)),
  // Prevent repeating HTTP somehow...
);

// Public
this.files = folderIDAndPage.pipe(
  switchMap(([folderID, page]) => fileService.getFiles(folderID, page)),
  // Prevent repeating HTTP somehow...
);

На данный момент у меня есть такое, что если я не подпишусь ни на один, HTTP не будет выполнен,но если я подпишусь на файлы или папки, folderService.getFoldersFromSegments будет вызываться дважды.

1 Ответ

0 голосов
/ 11 июня 2019

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

Я предлагаю использовать Subject вместо ReplaySubject и добавить shareReplay(1) позже в трубу, чтобы избавиться от 1. Также удалите publishReplay(1), refCount(), чтобы избавиться от поздних 2.

const sub = new Subject();
const source = combineLatest(
  of('World'),
  sub,
).pipe(
  map(([, n]) => n) ,
  shareReplay(1),
  tap(x => console.log('Tap', x)),
);

https://stackblitz.com/edit/rxjs-2zyxzf

...