Skip to content

Commit b862baa

Browse files
committed
Add possibility to filter requests that shouldn't be caught by the interceptor by providing an array of regex
1 parent 94c2d02 commit b862baa

File tree

4 files changed

+85
-8
lines changed

4 files changed

+85
-8
lines changed

README.MD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ You can too customize the background-color and the spinner type :
5454
<spinner [backgroundColor]="'#ff0000'" [spinner]="Spinkit.skWave"></spinner>
5555
```
5656

57+
You can filter the requests that shouldn't be caught by the interceptor by providing an array of regex patterns :
58+
```xml
59+
<spinner
60+
[backgroundColor]="'#ff0000'"
61+
[spinner]="Spinkit.skWave"
62+
[filteredUrlPatterns]="['\\d', '[a-zA-Z]', 'my-api']>
63+
</spinner>
64+
```
65+
5766
The different spinners available are referenced in [this class](src/app/spinkits.ts).
5867
5968
## Requirements

src/app/pending-interceptor.service.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'rxjs/add/observable/throw';
2020
export class PendingInterceptorService implements HttpInterceptor {
2121
private _pendingRequests = 0;
2222
private _pendingRequestsStatus: Subject<boolean> = new Subject<boolean>();
23+
private _filteredUrlPatterns: RegExp[] = [];
2324

2425
get pendingRequestsStatus(): Observable<boolean> {
2526
return this._pendingRequestsStatus.asObservable();
@@ -29,11 +30,25 @@ export class PendingInterceptorService implements HttpInterceptor {
2930
return this._pendingRequests;
3031
}
3132

33+
get filteredUrlPatterns(): RegExp[] {
34+
return this._filteredUrlPatterns;
35+
}
36+
37+
private shouldBypass(url: string): boolean {
38+
return this._filteredUrlPatterns.some((e: RegExp) => {
39+
return e.test(url);
40+
});
41+
}
42+
3243
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
33-
this._pendingRequests++;
44+
const shouldByPass = this.shouldBypass(req.url);
45+
46+
if (!shouldByPass) {
47+
this._pendingRequests++;
3448

35-
if (1 === this._pendingRequests) {
36-
this._pendingRequestsStatus.next(true);
49+
if (1 === this._pendingRequests) {
50+
this._pendingRequestsStatus.next(true);
51+
}
3752
}
3853

3954
return next.handle(req).map(event => {
@@ -43,10 +58,12 @@ export class PendingInterceptorService implements HttpInterceptor {
4358
return Observable.throw(error);
4459
})
4560
.finally(() => {
46-
this._pendingRequests--;
61+
if (!shouldByPass) {
62+
this._pendingRequests--;
4763

48-
if (0 === this._pendingRequests) {
49-
this._pendingRequestsStatus.next(false);
64+
if (0 === this._pendingRequests) {
65+
this._pendingRequestsStatus.next(false);
66+
}
5067
}
5168
});
5269
}

src/app/spinner/spinner.component.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,41 @@ describe('SpinnerComponent', () => {
141141
expect(component.isSpinnerVisible).toBeFalsy();
142142
})
143143
);
144+
145+
it('should not show the spinner if the request is filtered',
146+
inject(
147+
[PendingInterceptorService, HttpClient, HttpTestingController],
148+
(service: PendingInterceptorService, http: HttpClient, httpMock: HttpTestingController) => {
149+
component.filteredUrlPatterns.push('fake');
150+
fixture.detectChanges();
151+
152+
http.get('/fake').subscribe();
153+
expect(component.isSpinnerVisible).toBeFalsy();
154+
httpMock.expectOne('/fake').flush({});
155+
})
156+
);
157+
158+
it('should correctly filter with several requests and one pattern',
159+
inject(
160+
[PendingInterceptorService, HttpClient, HttpTestingController],
161+
(service: PendingInterceptorService, http: HttpClient, httpMock: HttpTestingController) => {
162+
component.filteredUrlPatterns.push('\\d');
163+
fixture.detectChanges();
164+
165+
http.get('/12345').subscribe();
166+
expect(component.isSpinnerVisible).toBeFalsy();
167+
httpMock.expectOne('/12345').flush({});
168+
169+
http.get('/fake').subscribe();
170+
expect(component.isSpinnerVisible).toBeTruthy();
171+
httpMock.expectOne('/fake').flush({});
172+
expect(component.isSpinnerVisible).toBeFalsy();
173+
})
174+
);
175+
176+
it('should throw an error if filteredUrlPatterns is not an array', () => {
177+
component.filteredUrlPatterns = null;
178+
expect(() => fixture.detectChanges())
179+
.toThrow(new Error('`filteredUrlPatterns` must be an array.'));
180+
});
144181
});

src/app/spinner/spinner.component.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
88
*/
99

10-
import { Component, Input, OnDestroy } from '@angular/core';
10+
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
1111
import { Subscription } from 'rxjs/Subscription';
1212
import { Spinkit } from '../spinkits';
1313
import { PendingInterceptorService } from '../pending-interceptor.service';
@@ -27,7 +27,7 @@ import { PendingInterceptorService } from '../pending-interceptor.service';
2727
'./spinkit-css/sk-wave.css',
2828
]
2929
})
30-
export class SpinnerComponent implements OnDestroy {
30+
export class SpinnerComponent implements OnDestroy, OnInit {
3131
public isSpinnerVisible: boolean;
3232
private subscription: Subscription;
3333
public Spinkit = Spinkit;
@@ -36,6 +36,8 @@ export class SpinnerComponent implements OnDestroy {
3636
public backgroundColor: string;
3737
@Input()
3838
public spinner = Spinkit.skCubeGrid;
39+
@Input()
40+
public filteredUrlPatterns: string[] = [];
3941

4042
constructor(private pendingRequestInterceptorService: PendingInterceptorService) {
4143
this.subscription = this.pendingRequestInterceptorService
@@ -45,6 +47,18 @@ export class SpinnerComponent implements OnDestroy {
4547
});
4648
}
4749

50+
ngOnInit(): void {
51+
if (!(this.filteredUrlPatterns instanceof Array)) {
52+
throw new TypeError('`filteredUrlPatterns` must be an array.');
53+
}
54+
55+
if (!!this.filteredUrlPatterns.length) {
56+
this.filteredUrlPatterns.forEach(e => {
57+
this.pendingRequestInterceptorService.filteredUrlPatterns.push(new RegExp(e));
58+
});
59+
}
60+
}
61+
4862
ngOnDestroy(): void {
4963
this.subscription.unsubscribe();
5064
}

0 commit comments

Comments
 (0)