Solution - AsyncSubject
Solution
import { AsyncSubject, fromEvent } from 'rxjs';
import { first, tap } from 'rxjs/operators';
const body = document.querySelector('body')!;
const clicks = fromEvent(body, 'mousedown').pipe(
tap((event: MouseEvent) => console.log(event.pageX, event.pageY))
);
/**
* 1. Create a new AsyncSubject and specify the generic type
* `MouseEvent` for the next notification..
*/
const asyncSubject = new AsyncSubject<MouseEvent>();
/**
* 2. Subscribe to the `AsyncSubject` and set the `x` and `y`
* input values to the `pageX` and `pageY` values from the
* `MouseEvent` object.
*/
const x = document.querySelector('#x') as HTMLInputElement;
const y = document.querySelector('#y') as HTMLInputElement;
asyncSubject.subscribe((event) => {
x.value = event.pageX.toString();
y.value = event.pageY.toString();
});
/**
* 3. Subscribee to the `clicks` observable using the `AsyncSubject`
* instance as the Observer.
*/
clicks.subscribe(asyncSubject);
/**
* 4. Complete the `AsyncSubject` when the button is clicked.
*/
const btn = document.querySelector('#btn') as HTMLButtonElement;
fromEvent(btn, 'click')
.pipe(
first(),
tap(() => {
// complete AsyncSubject
asyncSubject.complete();
})
)
.subscribe();
Let's review the solution code above:
- First we do a bit of setup.
We get a reference to the
HTMLBodyElementin the DOM, and we use thefromEvent()operator to add an event listener to thebodyelement'smousedownevents. Using thetap()operator we log out thepageXandpageYvalues as a side effect. - Next, create a new
AsyncSubjectand specify the generic type ofMouseEvent. - We then subscribe to the
AsyncSubjectinstance and set thexandyinput elementvalueproperties to thepageXandpageYvalues from theeventobject. - We subscribe to the
clicksObservable and set theasyncSubjectas the Observer. - Finally, we use the
fromEvent()operator to add an event listener to thebtnelement. Using thefirst()operator we will unsubscribe after the first next notification, and then using thetap()operator we invoke thecomplete()method on theAsyncSubject. Again, note that if anAsyncSubjectnever completes then the Observers will never receive a next notification.