FRP-inspired JavaScript
by Kim Maida
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.3/Rx.js"></script>
JavaScript
// create a time observable that adds an item every 1 second
// map so resulting stream contains event values
const time$ =
Rx.Observable
.timer(0, 1000)
.timeInterval()
.map(e => e.value);
// create a mouse movement observable
// throttle to every 350ms
// map so resulting stream pushes objects with x and y coordinates
const move$ =
Rx.Observable
.fromEvent(document, 'mousemove')
.throttleTime(350)
.map(e => { return {x: e.clientX, y: e.clientY} });
// merge time + mouse movement streams
// complete after 10 seconds
const source$ =
Rx.Observable
.merge(time$, move$)
.takeUntil(Rx.Observable.timer(10000));
// subscribe to merged source$ observable
// if value is a number, createTimeset()
// if value is a coordinates object, addPoint()
const subscription =
source$.subscribe(
// onNext
(x) => {
if (typeof x === 'number') {
createTimeset(x);
} else {
addPoint(x);
}
},
// onError
(err) => { console.warn('Error:', err); },
// onCompleted
() => { console.info('Completed'); }
);
// add element to DOM to list out points touched in a particular second
function createTimeset(n) {
const elem = document.createElement('div');
const num = n + 1;
elem.id = 't' + num;
elem.innerHTML = `<strong>${num}</strong>: `;
document.body.appendChild(elem);
}
// add points touched to latest time in stream
function addPoint(pointObj) {
// add point to last appended element
const numberElem = document.getElementsByTagName('body')[0].lastChild;
numberElem.innerHTML += ` (${pointObj.x}, ${pointObj.y}) `;
}