I have been diving into Rxjs and managed to put together a simple slideshow that updates the images every 5 seconds after clicking the start button. However, I am struggling to figure out how to pause/stop the API fetching process once the button is clicked again.
import './style.css';
import { tap, switchMap } from 'rxjs/operators';
import { fromEvent, Observable, timer } from 'rxjs';
function updateImages(
links: string[]
): void {
document.getElementById('slideshow').childNodes.forEach((node: ChildNode) => {
if (node.nodeType == Node.ELEMENT_NODE) {
if (links.length) {
let element: HTMLElement = node as HTMLElement;
element.classList.add('loading');
element.style.backgroundImage = "url('" + links.shift() + "')";
element.classList.remove('loading');
}
}
});
}
const apiUrl: string = 'https://dog.ceo/api/breeds/image/random';
const btn = document.getElementById('btn');
const btnEvents$ = fromEvent(btn, 'click');
const sub = btnEvents$.subscribe((result) => {
startPolling('dogs').subscribe((dogs) => {
updateImages(dogs.map(({ message }) => message));
});
btn.innerHTML = 'Stop';
console.log(btn.classlist);
});
function requestData(url: string): Observable<Array<{ message: string }>> {
return Observable.create((observer) => {
Promise.all([
fetch(url).then((response) => response.json()),
fetch(url).then((response) => response.json()),
fetch(url).then((response) => response.json()),
fetch(url).then((response) => response.json()),
])
.then((dogs) => {
console.log(dogs);
observer.next(dogs);
observer.complete();
})
.catch((err) => observer.error(err));
}).pipe(tap((data) => console.log('dogrequest', data)));
}
function startPolling(
category: string,
interval: number = 5000
): Observable<Array<{ message: string }>> {
const url = category === 'dogs' ? apiUrl : null;
console.log(url);
return timer(0, interval).pipe(switchMap((_) => requestData(url)));
}
Right now, the data keeps being fetched continuously and I can't make it stop.