Learn RxJS
Search…
Progress Bar
This recipe demonstrates the creation of an animated progress bar, simulating the management of multiple requests, and updating overall progress as each completes.

Example Code

Progress Bar
1
import './style.css';
2
3
import { Observable, of, empty, fromEvent, from } from 'rxjs';
4
import {
5
delay,
6
switchMapTo,
7
concatAll,
8
count,
9
scan,
10
withLatestFrom,
11
share
12
} from 'rxjs/operators';
13
14
const requestOne = of('first').pipe(delay(500));
15
const requestTwo = of('second').pipe(delay(800));
16
const requestThree = of('third').pipe(delay(1100));
17
const requestFour = of('fourth').pipe(delay(1400));
18
const requestFive = of('fifth').pipe(delay(1700));
19
20
const loadButton = document.getElementById('load');
21
const progressBar = document.getElementById('progress');
22
const content = document.getElementById('data');
23
24
// update progress bar as requests complete
25
const updateProgress = progressRatio => {
26
console.log('Progress Ratio: ', progressRatio);
27
progressBar.style.width = 100 * progressRatio + '%';
28
if (progressRatio === 1) {
29
progressBar.className += ' finished';
30
} else {
31
progressBar.className = progressBar.className.replace(' finished', '');
32
}
33
};
34
// simple helper to log updates
35
const updateContent = newContent => {
36
content.innerHTML += newContent;
37
};
38
39
const displayData = data => {
40
updateContent(`<div class="content-item">${data}</div>`);
41
};
42
43
// simulate 5 separate requests that complete at variable length
44
const observables: Array<Observable<string>> = [
45
requestOne,
46
requestTwo,
47
requestThree,
48
requestFour,
49
requestFive
50
];
51
52
const array$ = from(observables);
53
const requests$ = array$.pipe(concatAll());
54
const clicks$ = fromEvent(loadButton, 'click');
55
56
const progress$ = clicks$.pipe(switchMapTo(requests$), share());
57
58
const count$ = array$.pipe(count());
59
60
const ratio$ = progress$.pipe(
61
scan(current => current + 1, 0),
62
withLatestFrom(count$, (current, count) => current / count)
63
);
64
65
clicks$.pipe(switchMapTo(ratio$)).subscribe(updateProgress);
66
67
progress$.subscribe(displayData);
Copied!

html

1
<div class="progress-container">
2
<div class="progress" id="progress"></div>
3
</div>
4
5
<button id="load">
6
Load Data
7
</button>
8
9
<div id="data"></div>
Copied!
Thanks to @johnlinquist for the additional help with example!

Operators Used

Last modified 1yr ago