為了視覺化呈現 API 取得的進度,也避免使用者一直重複點擊按鈕,所以利用 Http interceptor,來裝上 Loading畫面。
Loading 畫面如果懶得自己刻,可以去 cssload.net 看看
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpResponse
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { LoadingService } from './loading.service';
@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
private requests: HttpRequest<any>[] = [];
private whiteList: string[] = [];
constructor(private loadingService: LoadingService) { }
isInWhiteList(url: string): boolean {
let result = false;
if (url) {
for (const whiteUrl of this.whiteList) {
if (url.includes(whiteUrl)) {
result = true;
break;
}
}
}
return result;
}
removeRequest(req: HttpRequest<any>): void {
if (!this.isInWhiteList(req.url)) {
const i = this.requests.indexOf(req);
if (i >= 0) {
this.requests.splice(i, 1);
}
if (this.requests.length === 0) {
this.loadingService.loading(false);
}
}
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!this.isInWhiteList(req.url)) {
if (this.requests.length === 0) {
this.loadingService.loading(true);
}
this.requests.push(req);
}
return new Observable(observer => {
const subscription = next.handle(req)
.subscribe(
event => {
if (event instanceof HttpResponse) {
this.removeRequest(req);
observer.next(event);
}
},
err => { this.removeRequest(req); observer.error(err); },
() => { this.removeRequest(req); observer.complete(); });
// teardown logic in case of cancelled requests
return () => {
this.removeRequest(req);
subscription.unsubscribe();
};
});
}
}
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LoadingService {
private _isLoading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
// 使 isLoading 可以被其他組件訂閱
public readonly isLoading$ = this._isLoading.asObservable();
constructor() { }
// 控制加載指示器的顯示和隱藏
loading(isVisible: boolean): void {
this._isLoading.next(isVisible);
}
}