如何使用 Http 为 Angular 2 中的特定组件正确使用进度微调器?
How to correctly use a progress spinner for a particular component in Angular 2 using Http?
我有一个基本的 Angular 组件如下。从这个组件中,我生成了一个 TestObj 类型的对象数组,并使用相同的数组对 if kth (0 <= k <= x.length 的所有元素进行同步 post-调用) 元素处理失败,数组的剩余部分不处理。
处理-component.component.ts
import { Component, OnInit } from "@angular/core";
import { FormBuilder, Form, FormGroup } from "@angular/forms";
import { Router } from "@angular/router";
import { processingService } from "./processing-component.service";
import { catchError, finalize, map } from "rxjs/operators";
import { concat } from "rxjs/observable/concat";
import { Observable, BehaviorSubject } from "rxjs";
export class TestObj {
processedFor:string;
isProcessingHappened: boolean ;
isProcessingSuccess: boolean;
constructor(isProcessingHappened,isProcessingSuccess) {
this.isProcessingHappened = isProcessingHappened;
this.isProcessingSuccess = isProcessingSuccess;
}
}
@Component({
selector: 'processing-component',
templateUrl: './processing-component.component.html',
styleUrls:['./processing-component.component.scss'],
providers: [ProcessingService]
})
export class ProcessingComponent {
constructor(private processingService: ProcessingService) { }
//some array generation logic to fetch arrayToProcess
public arrayToProcess: Array<TestObj>= [];
public displayedColumns: string[] = ['processedFor', 'isProcessingHappened', 'isProcessingSuccess']
public startBatchRun() {
const processes = this.arrayToProcess.map(details => this.processingService.runBatchExperiment(details).pipe(
map(() => {
this.isLoading.next(true);
details.isProcessingSuccess = true;
return this.arrayToProcess;
}),
catchError(() => {
this.isLoading.next(false);
details.isProcessingSuccess = false;
throw(false);
}),
finalize(() => {
this.isLoading.next(false);
details.isProcessingHappened = true;
}),
));
concat(...processes)
.map(() => this.isLoading = true)
.subscribe(res => {
})
}
}
我的服务如下所示
处理-component.service.ts
import { Injectable, Inject } from "@angular/core";
import { Http } from "@angular/http";
@Injectable()
export class ProcessingService {
constructor(@Inject('portfolioBaseUrl') private portfolioBaseUrl: string,
private http: Http) {}
processingUrl = this.portfolioBaseUrl + '/process/'
public runBatchExperiment(processingObj:TestObj ) {
return this.http.post(`${this.processingUrl}`,processingObj);
}
}
我的模板如下
处理-component.component.html
<button *ngIf = "arrayToProcess.length > 0" mat-raised-button (click) = "startBatchRun()" >Start Processing</button>
<div *ngIf = "arrayToProcess.length > 0" >
<mat-table [dataSource] = "arrayToProcess" >
<ng-container matColumnDef="processedFor">
<mat-header-cell *matHeaderCellDef> ID</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.processedFor }} </mat-cell> <!--add pipe here-->
</ng-container>
<ng-container matColumnDef="isProcessingHappened">
<mat-header-cell *matHeaderCellDef> Proceesing happened </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf = "element.isProcessingHappened === true" >done</mat-icon>
<mat-icon *ngIf = "element.isProcessingHappened === false" >error_outline</mat-icon>
</mat-cell>
</ng-container>
<ng-container matColumnDef="isProcessingSuccess">
<mat-header-cell *matHeaderCellDef> Batch success </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf = "element.isProcessingSuccess === true" >done</mat-icon>
<mat-icon *ngIf = "element.isProcessingSuccess === false" >error_outline</mat-icon>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
另外我想做的是显示一个进度微调器,当 post-调用一个类型为 TestObj 的对象时显示它,当我们从后端得到响应时隐藏它特定对象。此进度微调器必须完全禁用 UI 屏幕。
我尝试使用拦截器服务来实现相同的目的。问题在于拦截器显示整个前端进行的所有调用的进度微调器,而我想要实现的是做同样的事情,但仅针对 ProcessingComponent[= 进行的 http 调用40=]一个人。我尝试获取一个局部变量 isLoading
并在 ProcessingComponent
的 constructor
中将其设置为 false 并在执行 startBatchRun
时将 isLoading
设置为 true并在 startBatchRun
退出时将其设置为 false。有什么方法可以实现可观察管道的功能吗?
您应该查看 Angular Material 文档中描述的实现,在数据 table 示例下,特别是“Table retrieving data through HTTP”示例。
相关代码片段:
displayedColumns: string[] = ['created', 'state', 'number', 'title'];
data: GithubIssue[] = [];
isLoadingResults = true;
...
ngAfterViewInit() {
...
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.exampleDatabase!.getRepoIssues(this.sort.active, this.sort.direction, this.paginator.pageIndex);
}),
map(data => {
...
this.isLoadingResults = false;
...
return data.items;
}),
catchError(() => {
...
return observableOf([]);
})
).subscribe(data => this.data = data);
}
这样,你只需要一个局部布尔变量,hide/show根据变量状态的微调器。
如果你想对你的请求进行去抖动(所以它不会每次都显示,即使是最后 100ms
的请求),你可以在switchMap()
像这样:
...
switchMap(() => {
const result$ = this.exampleDatabase!.getRepoIssues(this.sort.active, this.sort.direction, this.paginator.pageIndex);
timer(100).pipe(takeUntil(result$)).subscribe(t => this.isLoadingResults = true);
}),
...
我有一个基本的 Angular 组件如下。从这个组件中,我生成了一个 TestObj 类型的对象数组,并使用相同的数组对 if kth (0 <= k <= x.length 的所有元素进行同步 post-调用) 元素处理失败,数组的剩余部分不处理。
处理-component.component.ts
import { Component, OnInit } from "@angular/core";
import { FormBuilder, Form, FormGroup } from "@angular/forms";
import { Router } from "@angular/router";
import { processingService } from "./processing-component.service";
import { catchError, finalize, map } from "rxjs/operators";
import { concat } from "rxjs/observable/concat";
import { Observable, BehaviorSubject } from "rxjs";
export class TestObj {
processedFor:string;
isProcessingHappened: boolean ;
isProcessingSuccess: boolean;
constructor(isProcessingHappened,isProcessingSuccess) {
this.isProcessingHappened = isProcessingHappened;
this.isProcessingSuccess = isProcessingSuccess;
}
}
@Component({
selector: 'processing-component',
templateUrl: './processing-component.component.html',
styleUrls:['./processing-component.component.scss'],
providers: [ProcessingService]
})
export class ProcessingComponent {
constructor(private processingService: ProcessingService) { }
//some array generation logic to fetch arrayToProcess
public arrayToProcess: Array<TestObj>= [];
public displayedColumns: string[] = ['processedFor', 'isProcessingHappened', 'isProcessingSuccess']
public startBatchRun() {
const processes = this.arrayToProcess.map(details => this.processingService.runBatchExperiment(details).pipe(
map(() => {
this.isLoading.next(true);
details.isProcessingSuccess = true;
return this.arrayToProcess;
}),
catchError(() => {
this.isLoading.next(false);
details.isProcessingSuccess = false;
throw(false);
}),
finalize(() => {
this.isLoading.next(false);
details.isProcessingHappened = true;
}),
));
concat(...processes)
.map(() => this.isLoading = true)
.subscribe(res => {
})
}
}
我的服务如下所示
处理-component.service.ts
import { Injectable, Inject } from "@angular/core";
import { Http } from "@angular/http";
@Injectable()
export class ProcessingService {
constructor(@Inject('portfolioBaseUrl') private portfolioBaseUrl: string,
private http: Http) {}
processingUrl = this.portfolioBaseUrl + '/process/'
public runBatchExperiment(processingObj:TestObj ) {
return this.http.post(`${this.processingUrl}`,processingObj);
}
}
我的模板如下
处理-component.component.html
<button *ngIf = "arrayToProcess.length > 0" mat-raised-button (click) = "startBatchRun()" >Start Processing</button>
<div *ngIf = "arrayToProcess.length > 0" >
<mat-table [dataSource] = "arrayToProcess" >
<ng-container matColumnDef="processedFor">
<mat-header-cell *matHeaderCellDef> ID</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.processedFor }} </mat-cell> <!--add pipe here-->
</ng-container>
<ng-container matColumnDef="isProcessingHappened">
<mat-header-cell *matHeaderCellDef> Proceesing happened </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf = "element.isProcessingHappened === true" >done</mat-icon>
<mat-icon *ngIf = "element.isProcessingHappened === false" >error_outline</mat-icon>
</mat-cell>
</ng-container>
<ng-container matColumnDef="isProcessingSuccess">
<mat-header-cell *matHeaderCellDef> Batch success </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf = "element.isProcessingSuccess === true" >done</mat-icon>
<mat-icon *ngIf = "element.isProcessingSuccess === false" >error_outline</mat-icon>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
另外我想做的是显示一个进度微调器,当 post-调用一个类型为 TestObj 的对象时显示它,当我们从后端得到响应时隐藏它特定对象。此进度微调器必须完全禁用 UI 屏幕。
我尝试使用拦截器服务来实现相同的目的。问题在于拦截器显示整个前端进行的所有调用的进度微调器,而我想要实现的是做同样的事情,但仅针对 ProcessingComponent[= 进行的 http 调用40=]一个人。我尝试获取一个局部变量 isLoading
并在 ProcessingComponent
的 constructor
中将其设置为 false 并在执行 startBatchRun
时将 isLoading
设置为 true并在 startBatchRun
退出时将其设置为 false。有什么方法可以实现可观察管道的功能吗?
您应该查看 Angular Material 文档中描述的实现,在数据 table 示例下,特别是“Table retrieving data through HTTP”示例。
相关代码片段:
displayedColumns: string[] = ['created', 'state', 'number', 'title'];
data: GithubIssue[] = [];
isLoadingResults = true;
...
ngAfterViewInit() {
...
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.exampleDatabase!.getRepoIssues(this.sort.active, this.sort.direction, this.paginator.pageIndex);
}),
map(data => {
...
this.isLoadingResults = false;
...
return data.items;
}),
catchError(() => {
...
return observableOf([]);
})
).subscribe(data => this.data = data);
}
这样,你只需要一个局部布尔变量,hide/show根据变量状态的微调器。
如果你想对你的请求进行去抖动(所以它不会每次都显示,即使是最后 100ms
的请求),你可以在switchMap()
像这样:
...
switchMap(() => {
const result$ = this.exampleDatabase!.getRepoIssues(this.sort.active, this.sort.direction, this.paginator.pageIndex);
timer(100).pipe(takeUntil(result$)).subscribe(t => this.isLoadingResults = true);
}),
...