如何为angular 5中的每个HTTP请求显示微调器?

如何为angular 5中的每个HTTP请求显示微调器?,angular,angular-http,angular-http-interceptors,angular-httpclient,Angular,Angular Http,Angular Http Interceptors,Angular Httpclient,我是新手。如何编写一个通用函数来显示angular 5中每个HTTP请求的微调器。请帮助我实现此功能。这与HttpClient或HTTP请求无关。这是一个如何处理一般异步调用(HTTP或非HTTP)的问题 你应该 <div class="spinner" *ngIf="loading"; else showWhenLoaded"><div> <ng-template #showWhenLoaded> <div>Your Content<

我是新手。如何编写一个通用函数来显示angular 5中每个HTTP请求的微调器。请帮助我实现此功能。

这与HttpClient或HTTP请求无关。这是一个如何处理一般异步调用(HTTP或非HTTP)的问题

你应该

<div class="spinner" *ngIf="loading"; else showWhenLoaded"><div>
<ng-template #showWhenLoaded>
    <div>Your Content</div>
</ng-template>
您可以使用Angular来显示所有请求的微调器,下面是一个很好的示例

此外,您还必须创建一个微调器服务/模块,并将其注入http侦听器中。最后,在拦截方法中,可以使用
Finally
rxJs方法停止微调器。下面是一个简单的实现:


intercept(req:HttpRequest

您可以创建一个服务,然后在订阅它的应用程序的根级别向它发布事件。让我解释一下

broadcast.service.ts(这是您的服务)

在应用程序组件级别:

this.broadcastService.subscribe('PROGRESS_START', ()=>{
  //hit when you start http call
  this.myLoader = true;
});
最后,在app.component.html中:

<div *ngIf="myLoader">
 <!--YOUR LOADER SHOULD GO HERE-->
</div>
<router-outlet></router-outlet>


这是一种非常通用的松耦合方式,可以实现您想要的任何加载程序。

在Angular的拦截器中,我使用了“do”操作符

intercept(req:HttpRequest,next:HttpHandler):可观察{
//成功和失败响应的处理程序
const onReqFinish=(事件:HttpEvent)=>{
如果(event.type==4){
this.onXhrFinish();
}
};
这个.onXhrStart();
返回下一个句柄(req)
.做(
完成时,
onReqFinish
);
}
来源

创建服务

//loader.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class LoaderService {

  public isLoading = new BehaviorSubject(false);
  constructor() { }
}
创建加载程序拦截器

    // loader.interceptors.ts
    import { Injectable } from '@angular/core';
    import {
        HttpErrorResponse,
        HttpResponse,
        HttpRequest,
        HttpHandler,
        HttpEvent,
        HttpInterceptor
    } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { LoaderService } from './loader.service';

    @Injectable()
    export class LoaderInterceptor implements HttpInterceptor {
        private requests: HttpRequest<any>[] = [];

        constructor(private loaderService: LoaderService) { }

        removeRequest(req: HttpRequest<any>) {
            const i = this.requests.indexOf(req);
            if (i >= 0) {
                this.requests.splice(i, 1);
            }
            this.loaderService.isLoading.next(this.requests.length > 0);
        }

        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

            this.requests.push(req);
            console.log("No of requests--->" + this.requests.length);
            this.loaderService.isLoading.next(true);
            return Observable.create(observer => {
                const subscription = next.handle(req)
                    .subscribe(
                        event => {
                            if (event instanceof HttpResponse) {
                                this.removeRequest(req);
                                observer.next(event);
                            }
                        },
                        err => {
                            alert('error returned');
                            this.removeRequest(req);
                            observer.error(err);
                        },
                        () => {
                            this.removeRequest(req);
                            observer.complete();
                        });
                // remove request from queue when cancelled
                return () => {
                    this.removeRequest(req);
                    subscription.unsubscribe();
                };
            });
        }
    }

完整的指南包含一个material
mat ProgressSpinner
用法。非常酷!

在这里,我编写了一些创建自定义progressbar的步骤

  • 创建一个组件

      //loader.interceptor.ts
      import { Component, OnInit } from '@angular/core';
      import { LoaderService } from '../loader.service';
    
      @Component({
        selector: 'app-loading',
        templateUrl: './loading.component.html',
        styleUrls: ['./loading.component.css']
      })
      export class LoaderComponent implements OnInit {
    
        loading: boolean;
        constructor(private loaderService: LoaderService) {
          this.loaderService.isLoading.subscribe((v) => {
            console.log(v);
            this.loading = v;
          });
        }
        ngOnInit() {
        }
    
      }
    
    从“@angular/core”导入{Component,Input}; @组成部分({ 选择器:“应用软件进度条”, 模板:
    
    
    , }) 导出类SWProgresbarComponent{ @Input()加载=false; 构造函数(){} }

  • 2在模块中导入组件:-

    import { SWProgresbarComponent } from '../sw-progressbar.component';
    @NgModule({
    declarations: [SWProgresbarComponent],
    imports: [
    CommonModule,
    MaterialModule,
    RouterModule
    ],
    exports: [SWProgresbarComponent,
    RouterModule
    ]
    })
    export class SharedModule { }
    
  • 如何使用它

    此处在要显示的组件中加载将为真 下面是要显示加载程序的组件中的代码

    对于微调器,将“垫进度”微调器替换为“垫进度”微调器


  • 创建拦截器服务

    import { Injectable } from '@angular/core';
    import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { finalize } from 'rxjs/operators';
    import { NgxSpinnerService } from 'ngx-spinner';
    
    @Injectable()
    export class SpinnerInterceptor implements HttpInterceptor {
    
        constructor(private spinner: NgxSpinnerService) { }
    
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            this.spinner.show();
            return next.handle(req).pipe(
                finalize(() => this.spinner.hide())
            );
        }
    }
    
    路由器插座内的最后一个in-app.component添加微调器标签

     <router-outlet>
        <ngx-spinner bdColor="rgba(0,0,0,0.8)"
                     size="medium"
                     color="#fff"
                     type="timer">
            <p style="color: #fff"> Loading... </p>
        </ngx-spinner>
    </router-outlet>
    
    
    加载


    正如您所见,我使用的是NgxSpinner,但如果您使用自定义微调器,这应该没有什么区别,您只需要创建服务来显示和隐藏微调器,并将此服务注入微调器拦截器中。

    您可以使用PaceJs,它不是特定于角度的,但它是开箱即用的。我认为显示单个微调器不是一个好主意任何xhr请求的HTTP加载器。将来可能需要更多详细信息检查此示例教程,以使用拦截器显示单个或多个请求的HTTP加载器。他也可以实现NGRX,但这不是他所问的“为每个HTTP请求显示微调器的通用函数”。这样,他就可以从应用程序中的任何位置发布进度开始事件。这样,您将向应用程序引入多少加载程序?每个需要单独获取的项目一个加载程序。如果您获取的动态数据仅在screenProb的一部分中使用,则不需要使用加载程序阻止整个应用程序可复制的:
    import { SWProgresbarComponent } from '../sw-progressbar.component';
    @NgModule({
    declarations: [SWProgresbarComponent],
    imports: [
    CommonModule,
    MaterialModule,
    RouterModule
    ],
    exports: [SWProgresbarComponent,
    RouterModule
    ]
    })
    export class SharedModule { }
    
    import { Injectable } from '@angular/core';
    import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { finalize } from 'rxjs/operators';
    import { NgxSpinnerService } from 'ngx-spinner';
    
    @Injectable()
    export class SpinnerInterceptor implements HttpInterceptor {
    
        constructor(private spinner: NgxSpinnerService) { }
    
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            this.spinner.show();
            return next.handle(req).pipe(
                finalize(() => this.spinner.hide())
            );
        }
    }
    
    import { HTTP_INTERCEPTORS } from '@angular/common/http';
                     
            ....
                 
    @NgModule({       
        providers: [
            { provide: HTTP_INTERCEPTORS, useClass: SpinnerInterceptor, multi: true }               
        ]
    })
    
     <router-outlet>
        <ngx-spinner bdColor="rgba(0,0,0,0.8)"
                     size="medium"
                     color="#fff"
                     type="timer">
            <p style="color: #fff"> Loading... </p>
        </ngx-spinner>
    </router-outlet>