Ajax Angular 2 HTTP进度条

Ajax Angular 2 HTTP进度条,ajax,http,angular,ionic2,Ajax,Http,Angular,Ionic2,angular2中目前是否有一种方法可以使用angular2/http模块检索ajax调用的进度(即完成百分比) 我使用以下代码进行HTTP调用: let body = JSON.stringify(params); let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: header

angular2中目前是否有一种方法可以使用angular2/http模块检索ajax调用的进度(即完成百分比)

我使用以下代码进行HTTP调用:

        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) => {
                ...
            });

目标是编写一个同步系统。帖子将返回大量数据,我想给用户一个同步需要多长时间的指示。

您可以利用XHR提供的
onprogress
事件(请参阅此plunkr:)

这样就可以获得有关下载进度的提示。Angular2不支持开箱即用,但您可以通过扩展
浏览器xhr
类将其插入:

@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);
  }
}
有关更多详细信息,请参见此问题:


当您在angular2中创建http CAL时,它返回一个可观察的响应类型,该响应在名为where the all magic Aching的类中创建

XHRConnection通过侦听XMLHttpRequest的加载事件来构建响应,这意味着它将在请求结束时返回一个响应

现在为了能够改变这种行为,我们需要让我们的连接类监听进度事件

因此,我们需要创建自定义连接类,以处理我们认为合适的响应

我是这样做的, 请注意,我的php API在一个请求中返回多个响应,这些响应是纯字符串

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

现在调用http.get将返回一系列响应。

我强烈建议使用此选项

否则,与xhr混在一起会让你错过会议、饼干和其他东西

此外,它将更具可移植性,更易于实现(从4.3.0版开始,当使用
@ngular/common/http
中的新
HttpClient
时),Angular提供了即时收听进度的功能。您只需按如下方式创建HTTPRequest对象:

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

const req = new HttpRequest('POST', '/upload/file', file, {
  reportProgress: true,
});
当您订阅请求时,您将在每个进度事件中收到调用的订阅:

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!');
  }
});

更多信息。

@Bartek Chichoki的回答是正确的,但对我的案子不起作用。 加上观察:“事件”对我起了作用

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

希望它有帮助

我希望可以避免使用XhreQuest:)实现,但对此无能为力;)事实上,Angular2的HTTP支持还不支持它,因此您需要明确依赖XHR…这非常有效,直到您升级到Angular 5,然后包失败,因为它引用了OpaqueToken。我更愿意学习这项技术,而不是复制某人的codesCheck update Angular文档:
const req = new HttpRequest('POST', '/upload/file', file, {
  reportProgress: true,
  observe: 'events'
});