Angular 2 HTTP 진행률 표시줄
Angular 2 내에서 Angular 2/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) => {
...
});
목표는 동기화 시스템을 작성하는 것입니다.게시물은 많은 데이터를 반환할 것이고, 저는 사용자에게 동기화가 얼마나 걸릴지 알려주고 싶습니다.
현재(v.4.3.0부터, 신규 사용 시)HttpClient
부터@ngular/common/http
) Angular를 사용하면 즉시 진행 상황을 들을 수 있습니다.아래와 같이 HTTP Request 개체를 생성하면 됩니다.
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!');
}
});
자세한 내용은 여기.
다음과 같은 이점을 활용할 수 있습니다.onprogress
XHR에서 제공하는 이벤트(이 플런크r: http://plnkr.co/edit/8MDO2GsCGiOJd2y2XbQk?p=preview) 참조).
이를 통해 다운로드 진행 상황에 대한 힌트를 얻을 수 있습니다.Angular2에서는 즉시 지원되지 않지만 확장하여 플러그를 꽂을 수 있습니다.BrowserXhr
클래스:
@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);
}
}
그리고 그것을 무시합니다.BrowserXhr
확장된 제공자:
bootstrap(AppComponent, [
HTTP_PROVIDERS,
provide(BrowserXhr, { useClass: CustomBrowserXhr })
]);
자세한 내용은 이 질문을 참조하십시오.
angular2에서 httpcal을 만들면 응답 유형의 관찰 가능 항목이 반환되며, 이 응답은 모든 마법이 발생하는 XHRConnection이라는 클래스 내에 생성됩니다.
XHR Connection은 XMLHttpRequest의 로드 이벤트를 수신하여 응답을 작성합니다. 즉, 요청이 끝나면 응답을 하나 반환합니다.
이제 이 동작을 변경하려면 연결 클래스에서 진행률 이벤트를 수신하도록 해야 합니다.
따라서 적합하다고 판단되는 대로 응답을 처리하기 위해 사용자 지정 연결 클래스를 만들어야 합니다.
저는 이렇게 했습니다. 제 php API는 단일 요청에서 다중 응답을 반환하며 이 응답은 일반 문자열입니다.
나의_친구들
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);
}
}
그리고 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})
]
.
.
.
이제 http.get을 호출하면 일련의 응답이 반환됩니다.
@Bartek Chichoki의 답변은 맞지만 제 경우에는 효과가 없었습니다.관찰 추가: '이벤트'가 제게 도움이 되었습니다.
const req = new HttpRequest('POST', '/upload/file', file, {
reportProgress: true,
observe: 'events'
});
도움이 되길 바랍니다.
이것을 사용하는 것을 강력히 추천합니다.
https://www.npmjs.com/package/angular-progress-http
그렇지 않으면 xhr을 가지고 장난치면 세션 쿠키와 다른 것들을 놓치게 될 것입니다.
게다가 휴대성이 더 좋고 구현이 훨씬 쉬울 것입니다.
언급URL : https://stackoverflow.com/questions/37158928/angular-2-http-progress-bar
'sourcetip' 카테고리의 다른 글
Android 앱이 릴리스 인증서로 서명되었는지 확인하려면 어떻게 해야 합니까? (0) | 2023.08.01 |
---|---|
데이터 테이블: 정의되지 않은 속성 스타일을 읽을 수 없습니다. (0) | 2023.08.01 |
php 오류는 정의되지 않은 mysqli_dll을 표시합니다. (0) | 2023.08.01 |
epoll은 나사산으로 안전합니까? (0) | 2023.08.01 |
ID 열 내에서 ASP.net Identity 2.0의 테이블 이름을 변경하는 방법은 무엇입니까? (0) | 2023.08.01 |