我用角度6写了一个serviceHelper。我想显示每个请求开始的加载图像,并在请求自动完成时关闭加载图像。因此,我需要在捕获到请求的开始和结束时使用eventHandler进行请求。 (也许捕获错误)。我创建一个加载程序拦截器。但是,拦截器无法捕获我的请求。
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import ServiceResult from '../models/common/service-result';
@Injectable({
providedIn: 'root'
})
export class ServiceHelper {
constructor(private http: HttpClient) { }
get<T>(modulePort, controllerName: string, methodName: string, params: HttpParams = null): Observable<ServiceResult<T>> {
return this.http.get<ServiceResult<T>>("http://localhost:5001/api/" + controllerName + "/" + methodName, { params: params });
}
post<T>(modulePort, controllerName: string, methodName: string, postedObject): Observable<ServiceResult<T>> {
return this.http.post<ServiceResult<T>>("http://localhost:5001/api/" + controllerName + "/" + methodName, postedObject);
}
}
ServiceResult.ts
abstract class ServiceResult<T> {
public abstract messages: string[];
public abstract resultType: int;
public abstract data: T;
}
export default ServiceResult;
loader-interceptor.ts
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { ServiceHelper } from '../helpers/service-helper';
@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
private currentRequests: number;
constructor(
private _httpService: ServiceHelper) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
debugger;
if (this._httpService.ukljuciLoader) {
console.log("Your request started");
return next.handle(request)
.pipe(
tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
console.log("Your request finished");
}
}, (err: any) => {
console.log("You get an error.");
})
);
} else {
return next.handle(request);
}
}
}
export const LoaderInterceptorProvider = {
provide: HTTP_INTERCEPTORS,
useClass: LoaderInterceptor,
multi: true
};
答案 0 :(得分:1)
您应该为此目的创建拦截器。这是我的:
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { LoaderService } from './loader.service';
import { HttpService } from '../shared/http.service';
@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
private currentRequests: number;
constructor(
private _loaderService: LoaderService,
private _httpService: HttpService) {
this.currentRequests = 0;
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this._httpService.ukljuciLoader) {
if (this._loaderService.autoloader) {
this.incrementRequestCount();
}
return next.handle(request)
.pipe(
tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
if (this._loaderService.autoloader) {
this.decrementRequestCount();
}
}
}, (err: any) => {
if (this._loaderService.autoloader) {
this.currentRequests = 0;
this._loaderService._toggleLoader.emit(false);
}
})
);
} else {
return next.handle(request);
}
}
private decrementRequestCount() {
if (--this.currentRequests === 0) {
this._loaderService._toggleLoader.emit(false);
}
}
private incrementRequestCount() {
if (this.currentRequests++ === 0) {
this._loaderService._toggleLoader.emit(true);
}
}
}
export const LoaderInterceptorProvider = {
provide: HTTP_INTERCEPTORS,
useClass: LoaderInterceptor,
multi: true
};
这是html:
<div class="loader-wrapper" *ngIf="loader">
<div class="loader"></div>
</div>
这是ts文件:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { LoaderService } from './loader.service';
@Component({
selector: 'app-loader',
templateUrl: './loader.component.html'
})
export class LoaderComponent implements OnInit, OnDestroy {
private ngUnsubscribe: Subject<any> = new Subject();
public loader = false;
constructor(
private _loaderService: LoaderService
) { }
ngOnInit() {
this._loaderService._toggleLoader
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
res => {
setTimeout(() => { this.loader = res; });
});
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
加载程序服务:
import { Injectable, EventEmitter } from '@angular/core';
@Injectable()
export class LoaderService {
public autoloader = true;
public _toggleLoader: EventEmitter<any>;
constructor() {
this._toggleLoader = new EventEmitter<any>();
}
toggleLoader(toggle: boolean) {
this._toggleLoader.emit(toggle);
}
}
应用模块
....
import { LoaderInterceptor, LoaderInterceptorProvider } from './loader/loader.interceptor';
@NgModule({
declarations: [
...
],
imports: [
...
LoaderModule,
...
],
providers: [
...
LoaderInterceptorProvider,
...
}
],
entryComponents: [..],
bootstrap: [AppComponent]
})
export class AppModule {
}
最终的CSS
.loader-wrapper {
position: fixed !important;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-position: center center;
background-color: rgba(255, 255, 255, 1);
z-index: 9998;
}
.loader {
position: relative;
left: 50%;
top: 50%;
height: 20vw;
width: 20vw;
margin: -10vw 0 0 -10vw;
border: 3px solid transparent;
border-top-color: #3498db;
border-bottom-color: #3498db;
border-radius: 50%;
z-index: 2;
-webkit-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
.loader:before {
content: "";
position: absolute;
top:2%;
bottom: 2%;
left: 2%;
right: 2%;
border: 3px solid transparent;
z-index: 2;
border-top-color: #db213a;
border-radius: 50%;
-webkit-animation: spin 3s linear infinite;
-moz-animation: spin 3s linear infinite;
-o-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
.loader:after {
content: "";
position: absolute;
top:5%;
bottom: 5%;
left: 5%;
right: 5%;
border: 3px solid transparent;
border-top-color: #dec52d;
z-index: 2;
border-radius: 50%;
-webkit-animation: spin 1.5s linear infinite;
-moz-animation: spin 1.5s linear infinite;
-o-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
/*Keyframes for spin animation */
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(0deg); /* IE 9 */
transform: rotate(0deg); /* Firefox 16+, IE 10+, Opera */
}
50% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(180deg); /* Firefox 16+, IE 10+, Opera */
}
100% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(360deg); /* Firefox 16+, IE 10+, Opera */
}
}
@-moz-keyframes spin {
0% {
-webkit-transform: rotate(0deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(0deg); /* IE 9 */
transform: rotate(0deg); /* Firefox 16+, IE 10+, Opera */
}
50% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(180deg); /* Firefox 16+, IE 10+, Opera */
}
100% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(360deg); /* Firefox 16+, IE 10+, Opera */
}
}
@-o-keyframes spin {
0% {
-webkit-transform: rotate(0deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(0deg); /* IE 9 */
transform: rotate(0deg); /* Firefox 16+, IE 10+, Opera */
}
50% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(180deg); /* Firefox 16+, IE 10+, Opera */
}
100% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(360deg); /* Firefox 16+, IE 10+, Opera */
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(0deg); /* IE 9 */
transform: rotate(0deg); /* Firefox 16+, IE 10+, Opera */
}
50% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(180deg); /* Firefox 16+, IE 10+, Opera */
}
100% {
-webkit-transform: rotate(360deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg); /* IE 9 */
transform: rotate(360deg); /* Firefox 16+, IE 10+, Opera */
}
}
这是我的http.service:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Url } from './global';
export interface IRequestOptions {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
body?: any;
}
export function httpServiceCreator(http: HttpClient) {
return new HttpService(http);
}
@Injectable()
export class HttpService {
ukljuciLoader: boolean;
public constructor(public http: HttpClient) {
// If you don't want to use the extended versions in some cases you can access the public property and use the original one.
// for ex. this.httpClient.http.get(...)
}
public get<T>(url: string, options?: IRequestOptions, loader: boolean = true): Observable<T> {
this.ukljuciLoader = loader;
return this.http.get<T>(Url + url, options);
}
public post<T>(url: string, params: Object, options?: IRequestOptions, loader: boolean = true): Observable<T> {
this.ukljuciLoader = loader;
return this.http.post<T>(Url + url, params, options);
}
public put<T>(url: string, params: Object, options?: IRequestOptions, loader: boolean = true): Observable<T> {
this.ukljuciLoader = loader;
return this.http.put<T>(Url + url, params, options);
}
public delete<T>(url: string, options?: IRequestOptions, loader: boolean = true): Observable<T> {
this.ukljuciLoader = loader;
return this.http.delete<T>(Url + url, options);
}
}
export const HttpServiceProvider = {
provide: HttpService,
useFactory: httpServiceCreator,
deps: [HttpClient]
};
这是我要启动加载程序时的调用:
someCall( userid: number) {
let bodyString = JSON.stringify(userid: userid );
let headers = new HttpHeaders({ 'Content-Type': 'application/JSON' });
return this._http.post<any>('serverapi/spme call', bodyString, { headers: headers });
}
这是我不希望加载程序启动的时间:
someCall( userid: number) {
let bodyString = JSON.stringify(userid: userid );
let headers = new HttpHeaders({ 'Content-Type': 'application/JSON' });
return this._http.post<any>('serverapi/spme call', bodyString, { headers: headers }, false);
}
答案 1 :(得分:0)
您应该使用订阅角度HTTP服务结果。 代码示例;
get<T>(modulePort, controllerName: string, methodName: string, params: HttpParams = null): Observable<ServiceResult<T>> {
return this.http.get<ServiceResult<T>>("http://localhost:5001/api/" + controllerName + "/" + methodName, { params: params }).subscribe(result=>result.json(), err=> console.log(err));
}
,您可以查找包含您的http包装器的git repo; https://github.com/mehmetkarpuz/Angular6-http-wrapper
答案 2 :(得分:0)
这是可以使用
HttpInterceptor
的最佳方案。
import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http';
import { Observable, pipe } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class LoaderInterceptorService implements HttpInterceptor {
constructor() { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.showLoader();
return next.handle(req).pipe(tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
this.onEnd();
}
},
(err: any) => {
this.onEnd();
}));
}
private onEnd(): void {
this.hideLoader();
}
private showLoader(): void {
//show the image here
}
private hideLoader(): void {
//hide the image
}
}
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { LoaderInterceptorService } from './_services/loader-interceptor.service';
...
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: LoaderInterceptorService,
multi: true
}
]