2 votes

Angular 2.0 Comment étendre BrowserXhr pour créer une barre de progression ?

J'essaie donc de créer une barre de progression précise qui se remplit en fonction de mon appel ajax.

Ce site aidé mais je pense que les choses ont peut-être un peu changé depuis qu'il a été écrit.

J'ai donc mon CustomBrowserXhr que j'ai ajouté aux fournisseurs de mon module d'application pour remplacer le BrowserXhr :-.

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {

constructor(private service: ProgressService) {}

    build(): any {
        let xhr = super.build();
        xhr.onprogress = (event) => {
            console.log(event, "event inside browser override");
            this.service.progressEventObservable.next(event);
        };
        return <any>(xhr);
    }
}

Je dispose alors d'un service de progression très basique auquel d'autres composants peuvent s'abonner :-.

@Injectable()
export class ProgressService {
    progressEventObservable:Subject<any> = new Subject();
    progressEvent$ = this.progressEventObservable.asObservable();
}

Je pensais que je pourrais simplement faire des appels http et que je verrais le journal de la console "event inside browser override" - en l'état actuel des choses, j'obtiens simplement l'erreur "EXCEPTION : browserXHR.build is not a function". Quelqu'un peut-il m'éclairer sur ce qui ne va pas ici ?

Merci d'avance.

2voto

wolfhoundjesse Points 498

Editar: J'ai ajouté l'appel à super(); et attaché quelques éléments utiles à l'objet événement.

Merci pour votre aide. Cela fonctionne pour moi. J'ai regroupé ces deux services dans un seul fichier par souci de concision :

import { Injectable } from '@angular/core';
import { BrowserXhr } from '@angular/http';
import { Subject } from 'rxjs/Rx';

@Injectable()
export class ProgressService {
    progressEventObservable: Subject<any> = new Subject();
    progressEvent$ = this.progressEventObservable.asObservable();
}

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {

constructor(private service: ProgressService) { super(); }

    build(): any {
        let xhr = super.build();
        let startTime = Date.now();
        xhr.upload.onprogress = (event) => {
            let timeElapsed = Date.now() - startTime;
            let uploadSpeed = event.loaded / (timeElapsed / 1000);
            let timeRemaining = Math.ceil(((event.total - event.loaded) / uploadSpeed));

            event.uploadTimeRemaining = timeRemaining;
            event.uploadSpeed = (uploadSpeed / 1024 / 1024).toFixed(2);
            event.percentCompleted = ((event.loaded / event.total) * 100).toFixed(0);
            console.log(event, "event inside browser override");
            this.service.progressEventObservable.next(event);
        };
        return <any>(xhr);
    }
}

J'ai ajouté les deux services à mon module principal, comme vous l'avez décrit :

providers: [
    ProgressService,
    { provide: BrowserXhr, useClass: CustomBrowserXhr }
],
bootstrap: [ AppComponent ]

Il s'est connecté à la console comme prévu. Ensuite, dans le composant où je télécharge des fichiers, j'ai dû forcer la détection des modifications, mais sinon, tout fonctionne bien :

constructor(
private cdr: ChangeDetectorRef,
private service: ProgressService
) { 
    this.service.progressEvent$.subscribe(event => {
        this.progress = event.percentCompleted;
        this.speed = event.uploadSpeed;
        this.timeRemaining = event.uploadTimeRemaining;
        this.cdr.detectChanges();
    });
}

J'ai essayé de le faire fonctionner avec async pipe, mais il ne mettait à jour que le dernier événement. Qu'est-ce que vous en pensez ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X