Skip to content

Instantly share code, notes, and snippets.

@ivanbatic
Created October 10, 2017 06:40
Show Gist options
  • Save ivanbatic/bb1495d74922dc0110c074f879e9baa7 to your computer and use it in GitHub Desktop.
Save ivanbatic/bb1495d74922dc0110c074f879e9baa7 to your computer and use it in GitHub Desktop.
Rx github fetch demo
const btnEl = document.getElementById("fetchButton");
const userList = document.getElementById("show_list");
const seriesInput = document.getElementById("series");
// Here we can push new rate limit reset times
const rateLimitReset = new Rx.ReplaySubject(1);
// Countdowns derived from reset times
const resetTicker = rateLimitReset
.map(time => Math.ceil(time - Date.now() / 1000))
.switchMap(seconds => {
return Rx.Observable.interval(1000).map(i => seconds - i - 1).take(seconds);
}).share();
// Retries after ticking came down to 0
const forceRetries = resetTicker.filter(v => v === 0).map(() => seriesInput.value);
// [1] Fetch GitHub users that match entered query
const userInput = Rx.Observable.fromEvent(seriesInput, "keyup")
.debounceTime(300)
.map(ev => ev.target.value)
.filter(txt => txt.length >= 3)
.distinctUntilChanged();
// [1] Make a request to github
const githubRequest = query => {
const fetched = fetch("https://api.github.com/search/users?q=" + query);
return Rx.Observable.fromPromise(fetched).switchMap(response => {
const json = Rx.Observable.fromPromise(response.json());
if (response.status === 200) {
return json;
}
return json.switchMap(r => Rx.Observable.throw(response));
});
};
// [1] Take just userInput
const fetches = Rx.Observable.merge(userInput, forceRetries)
.switchMap(input => githubRequest(input).catch(err => {
// [2] take rate limits
const remaining = Number(err.headers.get("X-RateLimit-Remaining"));
const reset = Number(err.headers.get("X-RateLimit-Reset"));
// [2] if we hit the rate limit, push the new reset time
if (remaining === 0) {
rateLimitReset.next(reset);
return Rx.Observable.empty();
}
return Rx.Observable.throw(err);
}));
fetches
.map(response => response.items)
.map(items => {
return items.reduce((acc, item) => acc + `<li>${item.login}</li>`, "")
})
.subscribe(output => {
userList.innerHTML = output;
}, (err) => {
console.log("Error!!", err);
});
resetTicker.filter(v => v > 0).subscribe(v => {
userList.innerHTML = "Cannot fetch data. Retrying in " + v + " seconds.";
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment