Hey there:
import Rx from 'rxjs';
function mockApi(endpoint, time, response) {
return new Rx.Observable(observer => {
console.log(`${endpoint}: Request initiated.`)
let active = true;
const id = setTimeout(() => {
console.log(`${endpoint}: Response received.`)
active = false;
observer.next(response);
observer.complete();
}, time);
return () => {
if(active) console.log(`${endpoint}: Cancel operation.`)
clearTimeout(id);
}
})
}
function fetchFromApi() { return mockApi('Search', 4000, "This is a result of the search."); }
//============================================================
const messages$ = new Rx.Subject();
const trigger$ = messages$.filter(m => m === 'toggle');
const completedSearch$ = trigger$.flatMap(() =>
fetchFromApi().takeUntil(trigger$)
);
completedSearch$.subscribe(m => console.log('Subscriber:', m))
setTimeout(() => {
// Initiates API call.
trigger$.next('toggle');
}, 2000)
setTimeout(() => {
// Cancels ongoing API call without starting a new one.
trigger$.next('toggle');
}, 3000)
setTimeout(() => {
// Starts a new request.
trigger$.next('toggle');
}, 9000)
I aim to initiate and terminate an API call using the same trigger$
signal. The problem lies in how the code currently functions - it triggers a new API call each time. I want it to only halt an existing call when in progress, not commence a fresh one. Perhaps there's a need to detach the outermost flatMap
subscription from the trigger$
stream while fetchFromApi()
runs. Any suggestions on restructuring the code for this desired behavior? What's the ideal RxJS approach here?
UPDATE: After further exploration and referencing user guides, I arrived at this solution:
const completedSearch$ = trigger$.take(1).flatMap(() =>
fetchFromApi().takeUntil(trigger$)
).repeat()
Operates as intended. Still seems slightly enigmatic. Is this the typical RxJS methodology to resolve such scenarios?