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
verifyPasscodehigher-order function that accepts thepasscodeand an optionaltimeout. - The function returns a function that accepts the
sourceObservable and returns anObservablethat emitsbooleannext notifications. - Using the
sourceObservable we pipe to thewindow()operator. We provide thewindow()operator awindowBoundariesObservable. Thewindow()operator will create a new Observable that contains the buffered values when thewindowBoundariesObservable emits a next notification. ThewindowBoundariesObservable that we provide to thewindow()operator is oursourceObservable that we debounce for the specifiedtimeout. - Similar to the previous exercise using the
pipe()function, we then use themergeMap()operator that receives thepasscodearray 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 knownpasscodeObservable, 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.