👋
Working on learning RxJS for fun and since Svelte is able to use observables directly in its templates, it makes for a great pairing!
For several years I've had the convenience of using react-query which, among many things, has a core set of features I like:
- It establishes a pattern for managing your queries and mutations.
- It will prevent the same GET request from firing multiple times even if there are multiple components using it.
- Data is cached until you want new data (you can specify other rules and strategies around this but I'm not interested in them for this project).
This code is a rough draft of implementing those key points of functionality with RxJS. This code could, in theory, later be reduced down and made easily re-usable for many requests.
refreshRepos
calls next
on the _refreshRepos
Subject
. It sends the date because... I decided it would.
repos$
works something like this:
- We use
concat
so initially we'll setloading: true
whenever we're fetching data. - We then make a request to the
repos
endpoint, grab the response, then pass it along asdata
while settingloading: false
. - Using
scan
lets us keepdata
set to its previous value so we have the option of only showing a loading indicator on initial load. - I'm using
shareReplay(1)
to cover a few things:- Any components subscribing to
repos$
at the same time will not trigger an extra network call. All subscribers will receive the result of the first call until_refreshRepos.next()
is called again. - Any components that mount after completion of the first finished network call will receive the cached result rather than triggering a new call. This may be inconvenient in some situations but it suits what I wanted from this example. Feel free to adjust the code and share your variant.
- Any components subscribing to
- I found this functionality was possible by nesting the
ajax
call inside ofswitchMap
. Prior to that I couldn't get the network call to fire again when clicking the button.
We import repos$
and refreshRepos
. There's a button that calls refreshRepos
.
If we have data, list the repos! Even if we're re-loading; the "loading" message will only be displayed on initial load so we can refresh data in the background without having the list flash (disappear then reappear) to the user.
You can use throttleTime
to limit how often _refreshRepos
will be called. This will not defer requests, it will prohibit requests by ignoring items from _refreshRepos
during the specified time window.
export const repos$ = _refreshRepos.pipe(
throttleTime(2000), // Two seconds
switchMap(() =>
...