it-swarm.com.de

Angular 2 HTTP-Fortschrittsbalken

Gibt es derzeit in Angular 2 eine Möglichkeit, den Fortschritt (d. H. Den prozentualen Prozentsatz) eines Ajax-Aufrufs mithilfe des Moduls angle2/http abzurufen?

Ich benutze folgenden Code für meine HTTP-Aufrufe:

        let body = JSON.stringify(params);
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        this.http.post(url, body, options)
            .timeout(10000, new Error('Timeout exceeded during login'))
            .toPromise()
            .then((res) => {
                ...
            }).catch((err) => {
                ...
            });

Ziel ist es, ein Synchronisationssystem zu schreiben. Der Beitrag wird eine Menge Daten zurückgeben, und ich möchte dem Benutzer mitteilen, wie lange die Synchronisierung dauert.

16
C. Sysmans

Derzeit (ab v. 4.3.0, wenn neue HttpClient von @ngular/common/http verwendet wird) ermöglicht Angular das Hören, um den sofortigen Fortschritt zu ermöglichen. Sie müssen lediglich das HTTPRequest-Objekt wie folgt erstellen:

import { HttpRequest } from '@angular/common/http';
...

const req = new HttpRequest('POST', '/upload/file', file, {
  reportProgress: true,
});

Und wenn Sie sich bei request anmelden, erhalten Sie bei jedem Fortschrittsereignis ein Abonnement:

http.request(req).subscribe(event => {
  // Via this API, you get access to the raw event stream.
  // Look for upload progress events.
  if (event.type === HttpEventType.UploadProgress) {
    // This is an upload progress event. Compute and show the % done:
    const percentDone = Math.round(100 * event.loaded / event.total);
    console.log(`File is ${percentDone}% uploaded.`);
  } else if (event instanceof HttpResponse) {
    console.log('File is completely uploaded!');
  }
});

Mehr Infos hier .

15
Bartek Cichocki

Sie können das von XHR bereitgestellte onprogress-Ereignis nutzen (siehe folgende Übersicht: http://plnkr.co/edit/8MDO2GsCGiOJd2y2XbQk?p=preview ).

Dadurch können Sie Hinweise zum Fortschritt des Downloads erhalten. Dies wird von Angular2 nicht standardmäßig unterstützt, aber Sie können es mit der erweiterten Klasse BrowserXhr einstecken:

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
  constructor(private service:ProgressService) {}
  build(): any {
    let xhr = super.build();
    xhr.onprogress = (event) => {
      service.progressEventObservable.next(event);
    };
    return <any>(xhr);
  }
}

und überschreiben Sie den BrowserXhr-Provider mit dem erweiterten:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(BrowserXhr, { useClass: CustomBrowserXhr })
]);

Weitere Informationen finden Sie in dieser Frage:

6

Bei der Erstellung von http-cals in angle2 wird ein Observable vom Typ Response zurückgegeben. Diese Antwort wird in der Klasse XHRConnection erstellt, in der die gesamte Magie stattfindet.

Die XHRConnection erstellt die Antwort durch Abhören des Ladeereignisses von XMLHttpRequest. Dies bedeutet, dass am Ende der Anforderung eine Antwort zurückgegeben wird.

Now Um dieses Verhalten ändern zu können, müssen wir dafür sorgen, dass unsere Verbindungsklasse das progress -Ereignis hört.

Daher müssen wir eine benutzerdefinierte Verbindungsklasse erstellen, um die Antwort so zu handhaben, wie wir es für richtig halten.

Ich habe es so gemacht, Beachten Sie, dass meine PHP-API mehrere Antworten in einer einzelnen Anforderung zurückgibt und diese Antworten einfache Zeichenfolgen sind.

mein_backend.ts

import {Injectable} from "angular2/core";
import {Observable} from "rxjs/Observable";
import {Observer} from "rxjs/Observer";
import {Connection,ConnectionBackend} from "angular2/src/http/interfaces";
import {ReadyState, RequestMethod, ResponseType} from "angular2/src/http/enums";
import {ResponseOptions} from "angular2/src/http/base_response_options";
import {Request} from "angular2/src/http/static_request";
import {Response} from "angular2/src/http/static_response";
import {BrowserXhr} from "angular2/src/http/backends/browser_xhr";
import {Headers} from 'angular2/src/http/headers';
import {isPresent} from 'angular2/src/facade/lang';
import {getResponseURL, isSuccess} from "angular2/src/http/http_utils"

export class MyConnection implements Connection { 
    readyState: ReadyState;
    request: Request;
    response: Observable<Response>;

    constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: ResponseOptions) {       
        this.request = req;
        this.response = new Observable<Response>((responseObserver: Observer<Response>) => {
            let _xhr: XMLHttpRequest = browserXHR.build();
            _xhr.open(RequestMethod[req.method].toUpperCase(), req.url);
            // save the responses in array 
            var buffer :string[] = []; 
            // load event handler
            let onLoad = () => {
                let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
                //_xhr.respons 1 = "Loading data!"
                //_xhr.respons 2 = "Loading data!Ready To Receive Orders."
                // we need to fix this proble 
                // check if the current response text contains the previous then subtract
                // NOTE: I think there is better approach to solve this problem.
                buffer.Push(body);
                if(buffer.length>1){
                    body = buffer[buffer.length-1].replace(buffer[buffer.length-2],'');
                }
                let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
                let url = getResponseURL(_xhr);
                let status: number = _xhr.status === 1223 ? 204 : _xhr.status;
                let state:number = _xhr.readyState;
                if (status === 0) {
                    status = body ? 200 : 0;
                }
                var responseOptions = new ResponseOptions({ body, status, headers, url });
                if (isPresent(baseResponseOptions)) {
                    responseOptions = baseResponseOptions.merge(responseOptions);
                }
                let response = new Response(responseOptions);
                //check for the state if not 4 then don't complete the observer
                if(state !== 4){
                    //this will return stream of responses
                    responseObserver.next(response);
                    return;
                }
                else{
                    responseObserver.complete();
                    return;
                }
                responseObserver.error(response);
            };
            // error event handler
            let onError = (err: any) => {
                var responseOptions = new ResponseOptions({ body: err, type: ResponseType.Error });
                if (isPresent(baseResponseOptions)) {
                    responseOptions = baseResponseOptions.merge(responseOptions);
                }
                responseObserver.error(new Response(responseOptions));
            };

            if (isPresent(req.headers)) {
                req.headers.forEach((values, name) => _xhr.setRequestHeader(name, values.join(',')));
            }
            _xhr.addEventListener('progress', onLoad);
            _xhr.addEventListener('load', onLoad);
            _xhr.addEventListener('error', onError);

            _xhr.send(this.request.text());

            return () => {
                _xhr.removeEventListener('progress', onLoad);
                _xhr.removeEventListener('load', onLoad);
                _xhr.removeEventListener('error', onError);
                _xhr.abort();
            };
        });
    }
}
@Injectable()
export class MyBackend implements ConnectionBackend {
  constructor(private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions) {}
  createConnection(request: Request):MyConnection {
    return new MyConnection(request, this._browserXHR, this._baseResponseOptions);
  }
}

Und in der app.component.ts

import {Component, provide} from 'angular2/core';
import {HTTP_PROVIDERS,XHRBackend} from 'angular2/http';
import {MyBackend} from './my_backend';
@Component({
    selector: 'my-app',
    providers:  [
        HTTP_PROVIDERS,
        MyBackend,
        provide(XHRBackend, {useExisting:MyBackend})
    ]
    .
    .
    .

Now Beim Aufruf von http.get wird ein Steam der Antworten zurückgegeben.

3
matrmawi

Ich kann dies nur wärmstens empfehlen 

https://www.npmjs.com/package/angular-progress-http

wenn Sie sonst mit xhr herumspielen, verpassen Sie Sitzungscookies und andere Dinge

außerdem ist es portabler und einfacher zu implementieren

1
fdsfdsfdsfds