Как да покажа spinner за всяка HTTP заявка в angular 5?

нов съм в angular 5. Как да кодирам обща функция за показване на spinner за всяка HTTP заявка в angular 5. Моля, помогнете ми да внедря това.


person Harish    schedule 30.04.2018    source източник
comment
Можете да използвате PaceJs, той не е специфичен за ъгъла, но прави това веднага   -  person Jamie Rees    schedule 30.04.2018
comment
Мисля, че не е добра идея да се показва един спинер за ВСЯКА xhr заявка. Вероятно ще имате нужда от повече подробности в бъдеще   -  person David Votrubec    schedule 30.04.2018
comment
stackoverflow.com/questions/48385627/   -  person Eliseo    schedule 30.04.2018


Отговори (8)


Можете да използвате Angular HttpInterceptor, за да покажете спинер за всички ваши заявки, Ето един добър https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

Освен това ще трябва да създадете spinner услуга/модул и да я инжектирате във вашия http прихващач. И накрая, във вашия метод за прихващане можете да използвате метода finally rxJs, за да спрете своя спинер. Ето една проста реализация:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.spinnerService.start();
    return next.handle(req).finally(res => this.spinnerService.stop() );
}

Наслади се!

Бонус: Ето пример за внедряване на услуга за въртене

person Mehdi Benmoha    schedule 30.04.2018
comment
Вероятно дубликат на: stackoverflow.com/questions/49385369/ - person Mehdi Benmoha; 30.04.2018

Източник Връзка

Създаване на услуга

//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 Interceptor

    // 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();
                };
            });
        }
    }

Сега създайте компонент за зареждане, след което добавете компонента на приложението

  //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() {
    }

  }
person Code Spy    schedule 28.04.2019

Пълното ръководство е тук с материално mat-progress-spinner използване. Много яко!

person trueboroda    schedule 12.07.2019

Това няма нищо общо с HttpClient или HTTP заявки. Въпросът е как да се обработват асинхронни повиквания като цяло (HTTP или не).

Трябва да имаш

<div class="spinner" *ngIf="loading"; else showWhenLoaded"><div>
<ng-template #showWhenLoaded>
    <div>Your Content</div>
</ng-template>

и в ts-файла:

loading: boolean = true;

methodToTriggerRequest() {
    this.loading = true;
    this.http.get(...).subscribe(response => {
        if (resposnseNotAnError(response)) {this.loading = false}
    })
}
person Phil    schedule 30.04.2018
comment
По този начин колко зареждащи устройства ще въведете в приложението? - person Rukshan Dangalla; 30.04.2018
comment
по един за всеки елемент, който трябва да бъде извлечен поотделно. Не е необходимо да блокирате цялото приложение с товарач, ако извличате динамични данни, които се използват само в една част на екрана - person Phil; 30.04.2018

Можете да създадете услуга и след това да публикувате събития в нея, докато сте в основното ниво на приложението, абонирано за нея. Нека обясня.

broadcast.service.ts (това е вашата услуга)

import { Injectable } from '@angular/core';

import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';

import 'rxjs/add/operator/filter'
import 'rxjs/add/operator/map'

/**
 * This class acting as event service bus for the entire app.
 * No Need to register the class as this registered in the root level.
 * Can just inject to componets.
 */
@Injectable()
export class BroadcastService {

    private _handler: Subject<Message> = new Subject<Message>();

    broadcast(type: string, payload: any = null) {
        this._handler.next({ type, payload });
    }

    subscribe(type: string, callback: (payload: any) => void): Subscription {
        return this._handler
            .filter(message => message.type === type)
            .map(message => message.payload)
            .subscribe(callback);
    }
}

interface Message {
    type: string;
    payload: any;
}

След това можете да публикувате и да се абонирате за събития като това:

вашето ниво на обслужване:

this.broadcastService.broadcast('PROGRESS_START');

На ниво компонент на вашето приложение:

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>

Това е много общ свободно свързан начин за внедряване на какъвто искате зареждащ механизъм.

person Rukshan Dangalla    schedule 30.04.2018
comment
Той също може да внедри NGRX, но не това е, което поиска - person Phil; 30.04.2018
comment
Той попита за обща функция за показване на spinner за всяка HTTP заявка. Така че по този начин той може просто да публикува събитие за начало на напредъка от всяко място в приложението. - person Rukshan Dangalla; 30.04.2018

Тук съм написал някои стъпки за създаване на ваша собствена лента за прогрес.

  1. Създайте компонент

    импортиране на {Component, Input} от '@angular/core'; @Component({ селектор: 'app-sw-progressbar', шаблон: <div *ngIf="loading"> <mat-progress-bar style="position:absolute; left:15px; width: calc(100% - 30px); height:5px;" color="primary" mode="indeterminate"> </mat-progress-bar> </div>, }) експортиран клас SWProgresbarComponent { @Input() loading = false; конструктор() {}}

2 Импортиране на компонент в модула:-

import { SWProgresbarComponent } from '../sw-progressbar.component';
@NgModule({
declarations: [SWProgresbarComponent],
imports: [
CommonModule,
MaterialModule,
RouterModule
],
exports: [SWProgresbarComponent,
RouterModule
]
})
export class SharedModule { }
  1. Как се използва?

    Тук зареждането ще бъде вярно в компонента, където искате да покажете. Добавете този код по-долу в компонента, където искате да покажете товарача.

    <app-sw-progressbar [loading]="loading"></app-sw-progressbar>

    За spinner заменете mat-progress-bar с mat-progress-spinner.

person Shashikant Pandit    schedule 07.05.2020

Създайте услуга за прихващане

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 }               
    ]
})

Последно в 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, но това не би трябвало да има значение, ако използвате персонализиран спинер, просто трябва да създадете услуга за показване и скриване на спинера и да инжектирате тази услуга в интерцептора на спинера.

person Ali Jamal    schedule 09.06.2021

В интерцептора на Angular съм използвал оператор "do".

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

    // handler for both success and fail response
    const onReqFinish = (event: HttpEvent<any>) => {
      if (event.type === 4) {
        this.onXhrFinish();
      }
    };

    this.onXhrStart();

    return next.handle(req)
     .do(
       onReqFinish,
       onReqFinish
     );
}

Функцията onXhrStart показва товарач, а onXhrFinish го скрива.

Целият работещ изходен код и демонстрацията са тук

person Alexander Levakov    schedule 30.07.2018