import { fromEvent, of, merge, empty, concat, defer } from 'rxjs';
import { format } from 'date-fns';
// track in progress saves
const input = document.getElementById('note-input');
const saveIndicator = document.querySelector('.save-indicator');
const keyup$ = fromEvent(input, 'keyup');
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(
map(e => e.target.value),
const savesInProgress$ = inputToSave$.pipe(
tap(_ => savesInProgress++)
const savesCompleted$ = inputToSave$.pipe(
tap(_ => savesInProgress--),
// ignore if additional saves are in progress
filter(_ => !savesInProgress),
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$)
If new save comes in when our completion observable is running, we want to switch to it for a status update.
saveIndicator.innerHTML = status;