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
HTMLBodyElement
in the DOM, and we use thefromEvent()
operator to add an event listener to thebody
element'smousedown
events. Using thetap()
operator we log out thepageX
andpageY
values as a side effect. - Next, create a new
AsyncSubject
and specify the generic type ofMouseEvent
. - We then subscribe to the
AsyncSubject
instance and set thex
andy
input elementvalue
properties to thepageX
andpageY
values from theevent
object. - We subscribe to the
clicks
Observable and set theasyncSubject
as the Observer. - Finally, we use the
fromEvent()
operator to add an event listener to thebtn
element. 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 anAsyncSubject
never completes then the Observers will never receive a next notification.