RxJS loading indicator on any ajax request
up vote
0
down vote
favorite
I need to show a loading indicator any time an ajax request occurs. Based on this question RxJs How to set default request headers? I believe I'll have to create an ajax wrapper to use.
My requirements are to start the loading indicator when a request occurs. It can start again if there is already a request running. When a request completes/errors, I need the loading to go away. It should only go away if all requests have completed though.
In axios I just use interceptors and have a counter. It's pretty simple. I really have no clue how to handle this with RxJS though. My guess would be it needs to do something similar, I just really don't know how to write it.
ajax rxjs redux-observable
add a comment |
up vote
0
down vote
favorite
I need to show a loading indicator any time an ajax request occurs. Based on this question RxJs How to set default request headers? I believe I'll have to create an ajax wrapper to use.
My requirements are to start the loading indicator when a request occurs. It can start again if there is already a request running. When a request completes/errors, I need the loading to go away. It should only go away if all requests have completed though.
In axios I just use interceptors and have a counter. It's pretty simple. I really have no clue how to handle this with RxJS though. My guess would be it needs to do something similar, I just really don't know how to write it.
ajax rxjs redux-observable
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I need to show a loading indicator any time an ajax request occurs. Based on this question RxJs How to set default request headers? I believe I'll have to create an ajax wrapper to use.
My requirements are to start the loading indicator when a request occurs. It can start again if there is already a request running. When a request completes/errors, I need the loading to go away. It should only go away if all requests have completed though.
In axios I just use interceptors and have a counter. It's pretty simple. I really have no clue how to handle this with RxJS though. My guess would be it needs to do something similar, I just really don't know how to write it.
ajax rxjs redux-observable
I need to show a loading indicator any time an ajax request occurs. Based on this question RxJs How to set default request headers? I believe I'll have to create an ajax wrapper to use.
My requirements are to start the loading indicator when a request occurs. It can start again if there is already a request running. When a request completes/errors, I need the loading to go away. It should only go away if all requests have completed though.
In axios I just use interceptors and have a counter. It's pretty simple. I really have no clue how to handle this with RxJS though. My guess would be it needs to do something similar, I just really don't know how to write it.
ajax rxjs redux-observable
ajax rxjs redux-observable
asked Nov 9 at 0:01
Josh Close
13k868115
13k868115
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
Build a custom HTTP client that exposes a loading BehaviorSubject. Every time a connection is opened increment the count and decrement the count each time a connection finishes. Have your loading indicator show when the connection count is greater than 0 and hide when it is 0.
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
Inrxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.
– Josh Close
Nov 9 at 14:25
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
|
show 1 more comment
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
Build a custom HTTP client that exposes a loading BehaviorSubject. Every time a connection is opened increment the count and decrement the count each time a connection finishes. Have your loading indicator show when the connection count is greater than 0 and hide when it is 0.
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
Inrxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.
– Josh Close
Nov 9 at 14:25
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
|
show 1 more comment
up vote
0
down vote
accepted
Build a custom HTTP client that exposes a loading BehaviorSubject. Every time a connection is opened increment the count and decrement the count each time a connection finishes. Have your loading indicator show when the connection count is greater than 0 and hide when it is 0.
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
Inrxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.
– Josh Close
Nov 9 at 14:25
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
|
show 1 more comment
up vote
0
down vote
accepted
up vote
0
down vote
accepted
Build a custom HTTP client that exposes a loading BehaviorSubject. Every time a connection is opened increment the count and decrement the count each time a connection finishes. Have your loading indicator show when the connection count is greater than 0 and hide when it is 0.
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
Build a custom HTTP client that exposes a loading BehaviorSubject. Every time a connection is opened increment the count and decrement the count each time a connection finishes. Have your loading indicator show when the connection count is greater than 0 and hide when it is 0.
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
class HttpClient {
constructor() {
this.connectionCount$ = new rxjs.BehaviorSubject(0);
this.loading$ = new rxjs.BehaviorSubject(false);
}
incrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() + 1);
if (this.connectionCount$.getValue() === 1) {
this.loading$.next(true);
}
}
decrementConnectionCount() {
this.connectionCount$.next(this.connectionCount$.getValue() - 1);
if (this.connectionCount$.getValue() === 0) {
this.loading$.next(false);
}
}
get(url) {
this.incrementConnectionCount();
setTimeout(() => { // Simulate a http call that takes 2 seconds
this.decrementConnectionCount();
}, 2000);
}
// Do the same for the other verbs, put, post, delete etc
}
const httpClient = new HttpClient();
// Anywhere you want a loading spinner subscribe to the loading observable and show and hide the spinner
httpClient.loading$.subscribe(loading => {
document.getElementById('loading').style.display = loading ? 'block' : 'none';
});
// Show the connection count
httpClient.connectionCount$.subscribe(connectionCount => {
document.getElementById('connectionCount').innerText = connectionCount;
});
// Each time you click the button you will simulate a http get that takes two seconds, press it multople times and it will show for 2 seconds after the last click
document.getElementById('load').addEventListener('click', () => {
httpClient.get('someUrl');
});
#loading {
display: none;
}
svg {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
<button id="load">Load</button> Connection count: <span id="connectionCount"></span>
<div id="loading"> <!-- Get a funky loading spinner from loading.io -->
<svg xmlns="http://www.w3.org/2000/svg" class="lds-cutiefox" width="80px" height="80px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<circle cx="50" cy="50" r="39.891" stroke="#ffc254" stroke-width="14.4" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="39.891" stroke="#fff1cf" stroke-width="7.2" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;55.1413599195142 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="32.771" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;45.299378454348094 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
<circle cx="50" cy="50" r="47.171" stroke="#000000" stroke-width="1" fill="none" stroke-dasharray="0 300">
<animate attributeName="stroke-dasharray" values="15 300;66.03388996804073 300;15 300" keyTimes="0;0.5;1" dur="1.5s" repeatCount="indefinite" calcMode="linear" keySplines="0 0.4 0.6 1;0.4 0 1 0.6" begin="-0.069s"/>
</circle>
</g>
<g transform="rotate(143.103 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1"/>
<path fill="#ffc254" stroke="#000000" d="M97.2,50c0,6.1-1.2,12.2-3.5,17.8l-13.3-5.4c1.6-3.9,2.4-8.2,2.4-12.4"/>
<path fill="#fff1cf" transform="translate(0,-0.1)" d="M93.6,50c0,1.2,0,2.4-0.1,3.6L93,57.2c-0.4,2-2.3,3.3-4.2,2.8l-0.2-0.1c-1.8-0.5-3.1-2.3-2.7-3.9l0.4-3 c0.1-1,0.1-2,0.1-3"/>
<path fill="#ffc254" stroke="#000000" d="M85.4,62.5c-0.2,0.7-0.5,1.4-0.8,2.1c-0.3,0.7-0.6,1.4-0.9,2c-0.6,1.1-2,1.4-3.2,0.8v0c-1.1-0.7-1.7-2-1.2-2.9 c0.3-0.6,0.5-1.2,0.8-1.8c0.2-0.6,0.6-1.2,0.7-1.8"/>
<path fill="#ffc254" stroke="#000000" d="M94.5,65.7c-0.3,0.9-0.7,1.7-1,2.6c-0.4,0.8-0.7,1.7-1.1,2.5c-0.7,1.4-2.3,1.9-3.4,1.3l0,0 c-1.1-0.7-1.5-2.2-0.9-3.4c0.4-0.8,0.7-1.5,1-2.3c0.3-0.8,0.7-1.5,0.9-2.3"/>
<path fill="#ffc254" stroke="#000000" d="M85.6,67c0,0.8,0.1,1.6,0.3,2.4c0.6-0.5,1.1-1,1.4-1.7c0.2-0.7,0.2-1.5-0.1-2.2C86.5,64,85.6,66.3,85.6,67z"/>
</g>
<g transform="rotate(80.5368 50 50)">
<animateTransform attributeName="transform" type="rotate" values="360 50 50;0 50 50" keyTimes="0;1" dur="1.5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1" begin="-0.15000000000000002s"/>
<path fill="#fff1cf" stroke="#000000" d="M91,33.6l-10,4c-0.4-1.2-1.1-2.4-1.7-3.5c-0.2-0.5,0.3-1.1,0.9-1C83.6,32.9,87.4,32.9,91,33.6z"/>
<path fill="#fff1cf" stroke="#000000" d="M83.2,36.7l10-4c-0.6-1.7-1.5-3.3-2.3-4.9c-0.3-0.7-1.2-0.6-1.4,0.1C87.6,31.1,85.7,34,83.2,36.7z"/>
<path fill="#ffc254" stroke="#000000" transform="translate(0,0.2)" d="M82.8,50c0-3.4-0.5-6.8-1.5-10c-0.2-0.8-0.4-1.5-0.3-2.3c0.1-0.8,0.4-1.6,0.7-2.4c0.7-1.5,1.9-3.1,3.7-4l0,0 c1.8-0.9,3.7-1,5.6-0.3c0.9,0.4,1.7,1,2.4,1.8c0.7,0.8,1.3,1.7,1.7,2.8c1.5,4.6,2.2,9.5,2.2,14.4"/>
<path fill="#fff1cf" transform="translate(0,0.3)" d="M86.4,50l0-0.9l-0.1-0.9l-0.1-1.9c0-0.9,0.2-1.7,0.7-2.3c0.5-0.7,1.3-1.2,2.3-1.4l0.3,0c0.9-0.2,1.9,0,2.6,0.6 c0.7,0.5,1.3,1.4,1.4,2.4l0.2,2.2l0.1,1.1l0,1.1"/>
<path fill="#000000" d="M88.6,36.6c0.1,0.3-0.2,0.7-0.6,0.8c-0.5,0.2-0.9,0-1.1-0.3c-0.1-0.3,0.2-0.7,0.6-0.8C88,36.1,88.5,36.2,88.6,36.6z"/>
<path fill="none" stroke="#000000" d="M86,38.7c0.2,0.6,0.8,0.9,1.4,0.7c0.6-0.2,0.9-0.9,0.6-2.1c0.3,1.2,1,1.7,1.6,1.5c0.6-0.2,0.9-0.8,0.8-1.4"/>
<path fill="#ffc254" stroke="#000000" d="M86.8,42.2l0.4,2.2c0.1,0.4,0.1,0.7,0.2,1.1l0.1,1.1c0.1,1.2-0.9,2.3-2.2,2.3h0c-1.3,0-2.5-0.8-2.5-1.9l-0.1-1 c0-0.3-0.1-0.6-0.2-1l-0.3-1.9"/>
<path fill="#ffc254" stroke="#000000" d="M96.2,40.2l0.5,2.7c0.1,0.5,0.2,0.9,0.2,1.4l0.1,1.4c0.1,1.5-0.9,2.8-2.2,2.8c-1.3,0-2.5-1.1-2.6-2.4l-0.1-1.2 c0-0.4-0.1-0.8-0.2-1.2l-0.4-2.5"/>
<path fill="none" stroke="#000000" d="M90.9,36.4c1.1-1.1,2.7-1.6,4.3-1.9"/>
<path fill="none" stroke="#000000" d="M91.6,37.5c1.3-0.5,2.8-0.8,4.2-0.7"/>
<path fill="none" stroke="#000000" d="M91.7,38.8c0.2-0.1,0.4-0.1,0.7-0.1c1.2-0.1,2.5,0,3.8,0.3"/>
<path fill="none" stroke="#000000" d="M85,38.4c-1.6-0.1-3.1,0.6-4.6,1.2"/>
<path fill="none" stroke="#000000" d="M85,39.5c-1.4,0.3-2.8,0.9-4,1.6"/>
<path fill="none" stroke="#000000" d="M85.5,40.4c-0.2,0-0.4,0.1-0.7,0.2c-1.1,0.5-2.2,1.1-3.2,1.8"/>
<path fill="#ff7bac" d="M92.8,34.2c0.1,0.3-0.3,0.8-0.9,1c-0.6,0.2-1.2,0.1-1.4-0.2c-0.1-0.3,0.3-0.8,0.9-1 C92.1,33.8,92.7,33.9,92.8,34.2z"/>
<path fill="#ff7bac" d="M82.2,38.2c0.1,0.3,0.7,0.3,1.3,0.1c0.6-0.2,1-0.6,0.9-0.9c-0.1-0.3-0.7-0.3-1.3-0.1 C82.5,37.5,82,37.9,82.2,38.2z"/>
<path fill="#000000" d="M90,35.7L89.3,36l-0.3-0.7c-0.3-0.9,0.1-1.9,0.9-2.3l0.7-0.3l0.3,0.7C91.3,34.4,90.9,35.4,90,35.7z"/>
<path fill="#000000" d="M85.3,37.4l0.7-0.2l-0.2-0.6c-0.3-0.8-1.3-1.2-2.1-0.8L82.9,36l0.2,0.6C83.5,37.4,84.4,37.7,85.3,37.4z"/>
</g></svg>
Loading...
</div>
edited Nov 11 at 1:32
answered Nov 9 at 0:19
Adrian Brand
2,45911018
2,45911018
Inrxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.
– Josh Close
Nov 9 at 14:25
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
|
show 1 more comment
Inrxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.
– Josh Close
Nov 9 at 14:25
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
In
rxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.– Josh Close
Nov 9 at 14:25
In
rxjs.ajax
? Are you referring to the .NET version of Rx? I'm using RxJS, the JavaScript version.– Josh Close
Nov 9 at 14:25
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
Assumed you were using Angular but realise that there is nothing in your post to suggest that.
– Adrian Brand
Nov 10 at 22:52
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
I gave you the skeleton code for a generic http client with a loading observable. Just replace the timeout with a real http call.
– Adrian Brand
Nov 10 at 23:42
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
When doing an actual ajax call, how do I know when it's complete? Do I subscribe to the response in the HttpClient and return that?
– Josh Close
Nov 14 at 20:25
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
Tap the observable, learnrxjs.io/operators/utility/do.html
– Adrian Brand
Nov 14 at 23:27
|
show 1 more comment
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53217947%2frxjs-loading-indicator-on-any-ajax-request%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown