2016-05-16 3 views
0

Während ich mit angular2 einem kleinen Hindernisse bin das Experimentieren kam:angular2 http requist Umgang CHUNKE die Antworten

  • ich PHP-Code Hexe habe Stücke von Antworten liefert mit "ob_flush".

  • im vorderen Ende habe ich erfolgreich "XHR = XMLHttpRequest" Anfragen und erhielt die Antworten und damit umgehen "xhr.onprogress()" und "xhr.onreadystatechange()" verwendet wird.

Jetzt wenn ich die gleiche Funktionalität mit angular2 http.get() zu bekommen versuchte, konnte ich die Ergebnisse, wie sie vom Server nicht ausgegeben ankommen! Stattdessen werden die Ergebnisse am Ende des Prozesses nach Empfang der letzten Antwort durch eckig angezeigt.
Ich denke, das Observer Objekt rxjs puffert die Antworten !.

Wie kann ich dieses Verhalten ändern?

hier ist mein PHP-Code, testing.php:

echo date('H:i:s')." Loading data!"; 
ob_flush(); 
flush(); 
sleep(5); 
echo "Ready to run!"; 

hier mein angular2 Code ist:

template: ` 
    <div> 
     <h3>experimenting!</h3> 
     <button (click)="callServer()">run the test</button> 
     <div>the server says: {{msg}}</div> 
    </div>` 
export class AppComponent { 
    msg:any; 
    constructor (private http:Http){} 
    callServer(){ 
    this.http.get("localhost/testing.php") 
      .subscribe(res=> this.msg= res.text()); 
    } 
} 

Wenn ich diesen Code ausführen es zeigt nach 5 Sekunden: (19:59:47 Daten werden geladen! Betriebsbereit!).

  • Es sollte sofort ausgegeben: (19.59.47 Daten werden geladen!).

  • Dann nach 5 Sekunden ersetzt die vorherige Nachricht mit: (Ready to run!)

Antwort

1

Sie müssen die BrowserXhr Klasse erweitern zu tun, dass verwendet, um den niedrigen Pegel XHR-Objekt zu konfigurieren:

@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 die BrowserXhr Anbieter mit dem erweiterten:

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

Siehe diese Frage für weitere Details:

0

Nach rxjs und Lesen Angular2 Quellcode zu studieren, kam ich mit dieser Lösung bis

Ich fand es besser ist, custom_backend zu machen, ich denke, das ist die empfohlene Vorgehensweise von Winkeln Dev Team.

my_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); 
    } 
} 

Im Hauptkomponente wir die kundenspezifische bakend so zu bieten haben:

providers: [ 
    HTTP_PROVIDERS, 
    PostSrevice, 
    MyBackend, 
    provide(XHRBackend, {useExisting:MyBackend}) 
] 

Jetzt wenn wir http.get() verwenden Es wird ein Strom von Observable

zurückgegeben