Soy nuevo en Angular2 y me preguntaba si hay alguna manera de mostrar un indicador de actividad para cada solicitud HTTP y ocultar la vista hasta que se haya completado?

OriginalEl autor Carlos Porras | 2016-05-27

4 Comentarios

  1. 17

    Es una manera de escribir un interceptor para Angular2 Http. Mediante la creación de su propio http instancia puede swap que cuando se arranque la aplicación por el uso de la “proporcionar” método. Una vez hecho esto un PubSub servicio puede ser creado para publicar y suscribirse a estos eventos desde su Http interceptor y emiten antes y después de los eventos en cada solicitud realizada.

    Un vivo ejemplo de ello puede verse en Plunker

    El Interceptor:

    import {Injectable} from 'angular2/core';
    import {HTTP_PROVIDERS, Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers} from 'angular2/http';
    import 'rxjs/Rx';
    import {PubSubService} from './pubsubService';
    
    @Injectable()
    export class CustomHttp extends Http {
      _pubsub: PubSubService
       constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, pubsub: PubSubService) {
            super(backend, defaultOptions);
            this._pubsub = pubsub;
        }
    
        request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
            return this.intercept(super.request(url, options));
        }
    
        get(url: string, options?: RequestOptionsArgs): Observable<Response> {
            return this.intercept(super.get(url,options));
        }
    
        post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {   
            return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
        }
    
        put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
            return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
        }
    
        delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
            return this.intercept(super.delete(url, options));
        }
    
        getRequestOptionArgs(options?: RequestOptionsArgs) : RequestOptionsArgs {
            if (options == null) {
                options = new RequestOptions();
            }
            if (options.headers == null) {
                options.headers = new Headers();
            }
            options.headers.append('Content-Type', 'application/json');
            return options;
        }
    
        intercept(observable: Observable<Response>): Observable<Response> {
          this._pubsub.beforeRequest.emit("beforeRequestEvent");
          //this will force the call to be made immediately..  
          observable.subscribe(
                null,
                null,
                () => this._pubsub.afterRequest.emit("afterRequestEvent");
              );  
          return observable
        }
    
    
    }
    

    Los Emisores

    import {Subject } from 'rxjs/Subject';
    
    export class RequestEventEmitter extends Subject<String>{
        constructor() {
            super();
        }
        emit(value) { super.next(value); }
    }
    
    export class ResponseEventEmitter extends Subject<String>{
        constructor() {
            super();
        }
        emit(value) { super.next(value); }
    }
    

    La PubSubService

    import {Injectable} from 'angular2/core';
    import {RequestEventEmitter, ResponseEventEmitter} from './emitter';
    
    @Injectable()
    export class PubSubService{
       beforeRequest:RequestEventEmitter;
       afterRequest:ResponseEventEmitter;
       constructor(){
           this.beforeRequest = new RequestEventEmitter();
           this.afterRequest = new ResponseEventEmitter();
       }
    }
    

    El arranque de la Aplicación

    //main entry point
    import {bootstrap} from 'angular2/platform/browser';
    import {provide} from 'angular2/core';
    import {Http, HTTP_PROVIDERS, XHRBackend, RequestOptions} from 'angular2/http';
    import {HelloWorldComponent} from './hello_world';
    import {CustomHttp} from './customhttp';
    import {PubSubService} from './pubsubService'
    
    bootstrap(HelloWorldComponent, [HTTP_PROVIDERS,PubSubService, 
        provide(Http, {
            useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, pubsub: PubSubService) 
               => new CustomHttp(backend, defaultOptions, pubsub),
            deps: [XHRBackend, RequestOptions, PubSubService]
        })
    ]).catch(err => console.error(err));
    

    Ahora en su componente de carga es muy fácil suscribirse a los eventos y establecer una propiedad para mostrar o no

    export class LoaderComponent implements OnInit {
        showLoader = false;
      _pubsub:PubSubService;
    
      constructor(pubsub: PubSubService) {
        this._pubsub = pubsub;
      }
       ngOnInit() {
         this._pubsub.beforeRequest.subscribe(data => this.showLoader = true);
         this._pubsub.afterRequest.subscribe(data => this.showLoader = false);   
      }
    }
    

    Mientras esto termina siendo un poco más de código, si usted está buscando para ser notificados en cada solicitud en la aplicación de este haría. Una cosa a tener en cuenta con el interceptor es ya una suscribirse es que se realiza para cada petición de forma inmediata a todas las solicitudes serán ejecutadas, que puede no ser lo que usted necesita en casos particulares. Una solución que es para apoyar a los regulares Angular2 Http y el uso de la CustomHttp como una segunda opción que se podría inyectar en donde sea necesario. Yo creo que en la mayoría de los casos la inmediata suscripción iba a funcionar bien. Me encantaría escuchar ejemplos de cuando no.

    Creo que se puede utilizar .¿en lugar de suscribir en la intercepción – Plunker. intercept(observable: Observable<Response>): Observable<Response> { this._pubsub.beforeRequest.emit("beforeRequestEvent"); return observable.do(() => this._pubsub.afterRequest.emit("afterRequestEvent")); }
    El uso de do() debe ser la respuesta correcta como @BrianChance sugirió que las solicitudes se hacen dos veces al suscribirse a ellos, ya que ellos son fríos observables. Mira en la pestaña de la red cuando se ejecuta el plunk.
    La aplicación descrita por @d1820, con el do() sugerido por @BrianChance trabajó como un encanto cuando se utiliza en Angular v2.0.1, pero tiene un pequeño problema, ya que actualizar a la v2.2.0. Ceteris paribus, las devoluciones de llamada que ahora se llama dos veces (tanto onSuccess y onError). He buscado un poco pero no podía encontrar lo que está mal ; además, no podía encontrar una 2.2.0 CDN para hacer un plunkr, pero debe ser fácil de reproducir en un proyecto local. ¿Alguien tiene alguna idea de lo que podría estar mal ?
    Cuando yo comente la CustomHttp.método de solicitud, sólo se ejecuta una vez. Adivinar super.consigue ahora las llamadas CustomHttp.solicitud a la que llama el super. Significa que sólo podría tener que implementar la petición en vez de cada verbo.
    El problema es el Http lib ha cambiado, y bajo la cubre todo el prototipo de los métodos (get, post, put, delete) hacen una solicitud a la base del método de Solicitud con las opciones apropiadas anulado. Para solucionar el problema, simplemente comentar o eliminar el Post, Put, Delete, métodos Get de la CustomHttp módulo. [Plunker] (embed.plnkr.co/A3rL1l). La intersección se debe realizar sólo en la base de la Solicitud de prototipo método.

    OriginalEl autor d1820

  2. 16

    Sí, usted necesita para manejar que para cada Vista :

    • Usted puede tener un servicio para la solicitud http que devuelve un
      Observable
    • En el Componente tendrá un estado de carga
    • Que usted necesita para establecer el estado de carga en true antes de solicitar los datos de la
      servidor, a continuación, establece en false cuando la captura de datos se realiza.
    • En el uso de la plantilla de la ngIf para ocultar/mostrar la carga o el contenido

      Ex :

    El Servicio :

    @Injectable()
    export class DataService {
        constructor(private http: Http) { }
    
        getData() {
           return this.http.get('http://jsonplaceholder.typicode.com/posts/2');
        }
    } 
    

    El Componente :

    @Component({
      selector: 'my-app',
      template : `
        <div *ngIf="loading == true" class="loader">Loading..</div>
        <div *ngIf="loading == false">Content.... a lot of content <br> more content</div>`
    }) 
    export class App {
      loading: boolean; 
    
      constructor(private dataService: DataService) {  }
    
      ngOnInit() {
        //Start loading Data from the Server
        this.loading = true;
    
        this.dataService.getData().delay(1500).subscribe( 
          requestData => { 
            //Data loading is Done
            this.loading = false;
    
            console.log('AppComponent', requestData);
          } 
      } 
    }
    

    Un ejemplo de trabajo puede ser encontrado aquí : http://plnkr.co/edit/HDEDDLOeiHEDd7VQaev5?p=preview

    fácil y simple. gran. ty

    OriginalEl autor tibbus

  3. 3

    Además @tibbus respuesta

    Esto es mejor para establecer “isLoading” tipo de Número y guárdelo en el servicio.

    booleanos:

    solicitud 1 inicia -> control de giro en -> solicitar a 2 comienza -> solicitar a 1 termina -> spinner off -> solicitar a 2 extremos

    con número:

    solicitud 1 inicia -> control de giro en -> solicitar a 2 comienza -> solicitar a 1 termina -> solicitar a 2 extremos -> spinner fuera

    Servicio

    @Injectable()
    export class DataService {
        constructor(private http: Http) { }
    
        private set fetchCounter(v:number) {
            this._fetchCounter = v;
            this.isLoadingSource.next(this._fetchCounter > 0)
        }
        private get fetchCounter() { return this._fetchCounter };
        private _fetchCounter:number = 0;
    
        private isLoadingSource = new Subject<boolean>();
        public isLoading = this.isLoadingSource.asObservable();
    
        public getData() {
            this.fetchCounter++;
            return this.http.get('http://jsonplaceholder.typicode.com/posts/2')
                .map(r => {
                    this.fetchCounter--;
                    return r;
                });
        }
    } 
    

    Usted sólo tiene que suscribirse a isLoading de cualquiera de sus componentes.

    OriginalEl autor stjimmy54

  4. 2

    Agregar un común DAL (data access layer) de la clase como esta y el uso de esta DAL clase en sus componentes.

    Agregar carga indicador como un servicio o componente y el uso de los estilos personalizados.

    export class DAL {
        private baseUrl: string = environment.apiBaseUrl;
    
        private getConsolidatedPath(path: string) {
            if (path.charAt(0) === '/') {
              path = path.substr(1);
            }
            return `${this.baseUrl}/${path}`;
        }
    
        private callStack = [];
    
        private startCall() {
            this.loadingIndicator.display(true);
            this.callStack.push(1);
        }
    
        private endCall() {
            this.callStack.pop();
            if (this.callStack.length === 0) {
                this.loadingIndicator.display(false);
            }
        }
    
    
        public get(path: string) {
            this.startCall();
            return this.http.get(this.getConsolidatedPath(path), { headers: this.getHeaders() })
                .map(response => response.json())
                .catch(e => this.handleError(e))
                .finally(() => this.endCall());
        }
        public put(path: string, data: any) {
            this.startCall();
            return this.http.put(this.getConsolidatedPath(path), data, { headers: this.getHeaders() })
                .map(response => response.json())
                .catch(e => this.handleError(e))
                .finally(() => this.endCall());
    
        }
    
        public post(path: string, data: any) {
            this.startCall();
            return this.http.post(this.getConsolidatedPath(path), data, { headers: this.getHeaders() })
                .map(response => response.json())
                .catch(e => this.handleError(e))
                .finally(() => this.endCall());
        }
        public delete(path: string, data: any) {
            this.startCall();
            return this.http.delete(this.getConsolidatedPath(path), { body: data, headers: this.getHeaders() })
                .map(response => response.json())
                .catch(e => this.handleError(e))
                .finally(() => this.endCall());
        }
    
        constructor(public http: Http, public loadingIndicator: LoadingIndicatorService) {
        }
    
    }
    

    OriginalEl autor Sarath

Dejar respuesta

Please enter your comment!
Please enter your name here