Solution - Higher-order Function Operator
Solution
import { from, fromEvent, Observable } from 'rxjs';
import {
debounceTime,
map,
mergeMap,
sequenceEqual,
take,
window
} from 'rxjs/operators';
const PASSCODE = [1, 1, 1, 1];
const buttons = document.querySelectorAll('.btn');
const verifyPasscode = (passcode: number[], timeout = 1000) => (
source: Observable<number>
): Observable<boolean> =>
source.pipe(
window(source.pipe(debounceTime(timeout))),
mergeMap((value) =>
from(value).pipe(take(passcode.length), sequenceEqual(from(passcode)))
)
);
fromEvent<MouseEvent>(buttons, 'click')
.pipe(
map((event: MouseEvent) => {
const target = event.target as HTMLButtonElement;
return parseInt(target.dataset.key!, 10);
}),
verifyPasscode(PASSCODE)
)
.subscribe({
error: console.error,
next: console.log,
complete: () => console.log('complete')
});
Let's review the solution code above:
- We have defined a new
verifyPasscode
higher-order function that accepts thepasscode
and an optionaltimeout
. - The function returns a function that accepts the
source
Observable and returns anObservable
that emitsboolean
next notifications. - Using the
source
Observable we pipe to thewindow()
operator. We provide thewindow()
operator awindowBoundaries
Observable. Thewindow()
operator will create a new Observable that contains the buffered values when thewindowBoundaries
Observable emits a next notification. ThewindowBoundaries
Observable that we provide to thewindow()
operator is oursource
Observable that we debounce for the specifiedtimeout
. - Similar to the previous exercise using the
pipe()
function, we then use themergeMap()
operator that receives thepasscode
array of numbers. Using thefrom()
operator we create a new Observable that emits each number value in sequence and then completes. Within thepipe()
of this new Observable we use thesequenceEqual()
operator to compare the Observable against the knownpasscode
Observable, which we also create using thefrom()
operator. - Finally, we add the newly created
verifyPasscode()
operator thepipe()
after themap()
operator for the Observable that was created using thefromEvent()
operator.