如何利用Angular HTTPClient的progress
事件来显示Get请求的百分比进度,该请求不一定是文件请求?
目前,HTTPClient的progress
事件在请求完成后触发。我希望在后端使用Content-Length
并确定前端加载的内容百分比。
我正在为网格加载大量行,需要在UI上显示增量进度。有可能吗?
答案 0 :(得分:5)
我知道这个问题比较老,但是,我在寻找类似问题的答案时偶然发现了这个问题,由于没有被接受的答案,我发布了解决方案。
我最近实现了一种通用方法,无论角度8中的类型如何,都为每个请求显示进度条。
首先,我创建了一个HttpInterceptor
,它将自动拦截reportProgress
选项设置为true
的每个http调用。
@Injectable()
export class HttpProgressInterceptor implements HttpInterceptor {
constructor(
private spinnerService: SpinnerService // my personal service for the progress bar - replace with your own
) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.reportProgress) {
// only intercept when the request is configured to report its progress
return next.handle(req).pipe(
tap((event: HttpEvent<any>) => {
if (event.type === HttpEventType.DownloadProgress) {
// here we get the updated progress values, call your service or what ever here
this.spinnerService.updateGlobalProgress(Math.round(event.loaded / event.total * 100)); // display & update progress bar
} else if (event.type === HttpEventType.Response) {
this.spinnerService.updateGlobalProgress(null); // hide progress bar
}
}, error => {
this.spinnerService.updateGlobalProgress(null); // hide progress bar
})
);
} else {
return next.handle(req);
}
}
}
您当然需要在您的module
中注册此拦截器:
@NgModule({
declarations: [
AppComponent,
...
],
imports: [
BrowserModule,
...
RouterModule.forRoot(appRoutes)
],
providers: [
...
{ provide: HTTP_INTERCEPTORS, useClass: HttpProgressInterceptor, multi: true },
...}
],
bootstrap: [AppComponent]
})
export class AppModule { }
基本上我们已经在这里完成了,剩下的就是我们需要改变调用api的方式。如果您希望使用此拦截器监视特定请求,则需要告诉angular报告HttpRequest上的进度:
@Injectable()
export class MyService {
constructor(
private http: HttpClient
) {}
myGetMethod() {
const url = "api/data/load/big/data";
const req = new HttpRequest("GET", url, {
reportProgress: true // this is important!
});
return this.http.request(req);
}
}
这种调用httpClient
的api的方法在调用.subscribe
时会传递一个不同的对象,因此在调用myGetMethod()
时需要注意这一点:
ngOnInit() {
this.myService.myGetMethod().subscribe((event: HttpEvent<any>) => {
if (event.type === HttpEventType.Response) {
const responseData = event.body;
console.dir(responseData); // do something with the response
}
});
}
我们还可以在这里监听HttpEventType.DownloadProgress
事件并更新此组件中的进度值-但这不是我的示例的重点。
提示:如果遇到未定义event.total
的问题-您必须检查REST后端是否确实提供了Content-Length
标头-如果此标头丢失,您将无法计算进度!
无论如何,我希望有一天能对某人有所帮助help
答案 1 :(得分:1)
这个怎么样:
CREATE TABLE foo(
dt DATE NOT NULL,
f1 REAL NOT NULL,
f2 REAL NOT NULL,
f3 REAL NOT NULL,
f4 REAL NOT NULL
);
SELECT AVG((f1+f2+f3+f4)/4) as fld_avg FROM
(
SELECT date_part('year', dt) AS year_part,
date_part('fortnight', dt) AS fortnight_part,
f1, f2, f3, f4
FROM foo
WHERE dt >= date_trunc('day', NOW() - '3 month')
) foo
GROUP BY year_part, fortnight_part
...
import { HttpEventType, HttpClient, HttpRequest} from '@angular/common/http';
答案 2 :(得分:1)
您可以使用
const req = new HttpRequest('POST', '/upload/file', file, {
reportProgress: true
});
接下来,将此请求对象传递给 HttpClient.request()方法,该方法返回一个 HttpEvents 的Observable,该事件由拦截器处理:
// The `HttpClient.request` API produces a raw event stream
// which includes start (sent), progress, and response events.
return this.http.request(req).pipe(
map(event => this.getEventMessage(event, file)),
tap(message => this.showProgress(message)),
last(), // return last (completed) message to caller
catchError(this.handleError(file))
);
最后,您可以使用它来提供帮助
/** Return distinct message for sent, upload progress, & response events */
private getEventMessage(event: HttpEvent<any>, file: File) {
switch (event.type) {
case HttpEventType.Sent:
return `Uploading file "${file.name}" of size ${file.size}.`;
case HttpEventType.UploadProgress:
// Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / event.total);
return `File "${file.name}" is ${percentDone}% uploaded.`;
case HttpEventType.Response:
return `File "${file.name}" was completely uploaded!`;
default:
return `File "${file.name}" surprising upload event: ${event.type}.`;
}
}