#rxjs #multicast
#rxjs #многоадресная рассылка
Вопрос:
Я играю с образцом «индикатора сохранения», который зависит от RxJS.
Вот полный исходный код:
import { fromEvent, of, merge, empty, concat, defer } from 'rxjs';
import {
delay,
map,
mergeMap,
tap,
debounceTime,
distinctUntilChanged,
mapTo,
filter,
share,
switchAll
} from 'rxjs/operators';
import { format } from 'date-fns';
// track in progress saves
let savesInProgress = 0;
// references
const input = document.getElementById('note-input');
const saveIndicator = document.querySelector('.save-indicator');
// streams
const keyup$ = fromEvent(input, 'keyup');
// fake save request
const saveChanges = value => {
return of(value).pipe(delay(1500));
};
/**
* Trigger a save when the user stops typing for 200ms
* After new data has been successfully saved, so a saved
* and last updated indicator.
*/
const inputToSave$ = keyup$.pipe(
debounceTime(200),
map(e => e.target.value),
distinctUntilChanged(),
share()//Here!!
);
const savesInProgress$ = inputToSave$.pipe(
mapTo(of('Saving')),
tap(_ => savesInProgress )
);
const savesCompleted$ = inputToSave$.pipe(
mergeMap(saveChanges),
tap(_ => savesInProgress--),
// ignore if additional saves are in progress
filter(_ => !savesInProgress),
mapTo(
concat(
// display saved for 2s
of('Saved!'),
empty().pipe(delay(2000)),
// then last updated time, defer for proper time
defer(() => of(`Last updated: ${format(Date.now(), 'MM/DD/YYYY hh:mm')}`))
)
)
);
merge(savesInProgress$, savesCompleted$)
.pipe(
/*
If new save comes in when our completion observable is running, we want to switch to it for a status update.
*/
switchAll()
)
.subscribe(status => {
saveIndicator.innerHTML = status;
});
И ссылка, по которой можно найти исходный код: https://www.learnrxjs.io/learn-rxjs/recipes/save-indicator
Мне интересно, зачем share()
здесь нужен оператор многоадресной рассылки. Я попытался удалить его, и поведение приложения не изменилось.
Может кто-нибудь, пожалуйста, объяснить, почему share()
здесь требуется оператор?
редактировать: Пожалуйста, также имейте в виду, что существует только одна подписка / subscribe.
Комментарии:
1. Попробуйте добавить
tap(console.log)
beforeshare
и посмотрите, действительно ли изменилось поведение.2. Спасибо за комментарий. Какую часть конвейера вы ожидали увидеть измененной? Я пробовал
tap
передshare
: ничего не меняется.3. комментарий @ritaj, вероятно, соответствовал тому, что вы увидите разницу, проявляющуюся в том, что регистрируется. Хотя вы подписываетесь только один раз в конце, вы можете видеть, что это подписка на
merge(savesInProgress$, saveComplete$)
, которая подписывается на них обоих. И каждый из них подписываетсяinputToSave$
, так что в итоге у вас будет 2 подписки на этот поток4. В данном случае это, вероятно, не имеет большого значения… возможно, это было бы немного эффективнее с помощью share(), поскольку он создаст только одного слушателя, а затем отключит, сопоставит и сравнит один раз, но IMO, это действительно не имеет большого значения в этом примере.
5. Спасибо вам обоим! Я не понял этого в отношении двух подписок.