Post 来自多个范围输入的值在 Angular 6 中随 debounceTime 发生变化
Post values from multiple range inputs on change in Angular 6 with debounceTime
在我的 Angular 6 项目中,我有一个包含 3 个范围输入和 1 个复选框的组件。
使用复选框,我可以 link 3 个范围输入中的 2 个的值,这样如果一个被更改,另一个也会相应地更改。
当复选框未选中时,第二个不会更新。
当其中一个范围输入发生变化时,所有 3 个控件的值都必须发送到 API.
到目前为止我是成功的。
问题是,当我更改范围输入时,会有 post 对 API 的突发请求。
我想减少请求的爆发。
在模板中我有以下控件:
<input class="my-custom-range" type="range" [min]="-1 * navControl.engine1.power.max" [max]="navControl.engine1.power.max" [(ngModel)]="controls.throttle1" (ngModelChange)="onChangeThrothel1($event)" [disabled]="!navControl.engine1.isOnline" >
<input class="my-custom-range" type="range" [min]="-1 * navControl.engine2.power.max" [max]="navControl.engine2.power.max" [(ngModel)]="controls.throttle2" (ngModelChange)="onChangeThrothel2($event)" [disabled]="!navControl.engine2.isOnline" >
<mat-slider min="-80" max="80" step="8" thumbLabel="true" vertical="true" [(ngModel)]="controls.mainHelm" (ngModelChange)="changeMainHelm($event)" [disabled]="!navControl.engine1.isOnline" style="margin-top: 4em; height: 100%"></mat-slider>
<mat-checkbox [(ngModel)]="syncEngines">Motor Sync</mat-checkbox>
我有一些接口是这样的:
export interface INavigationRequest {
engine1: IEngineRequest;
engine2: IEngineRequest;
}
export interface IEngineRequest {
id: number;
requestedPower: number;
isForwardPropultion: boolean;
requestedAngle: number;
correctionPower: number;
correctionAngle: number;
}
在 server.service.ts 我有以下内容:
updateEngines(params: INavigationRequest): Observable<INavigationResponse> {
console.log('update engines', params);
return this.http.post<INavigationResponse>(`${this.baseUrl}/api/navigation/post/`, params);
}
在 component.ts 我有以下内容:
public onChangeThrothel1(value): void {
if (value && this.syncEngines) {
this.controls.throttle2 = value;
}
console.log('1', this.controls.throttle1);
console.log('2', this.controls.throttle2);
this.updateNavControl();
}
public onChangeThrothel2(value): void {
if (value && this.syncEngines) {
this.controls.throttle1 = value;
}
console.log('1', this.controls.throttle1);
console.log('2', this.controls.throttle2);
this.updateNavControl();
}
public changeMainHelm(value): void {
if (value) {
this.controls.helm = value;
this.updateNavControl();
}
}
public updateNavControl(): void {
let params: INavigationRequest = {
engine1: {
id: this.navControl.engine1.id,
isForwardPropultion: this.navControl.engine1.isForwardPropultion,
requestedPower: this.controls.throttle1,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine1.power.correction,
correctionAngle: this.navControl.engine1.angle.correction
},
engine2: {
id: this.navControl.engine2.id,
isForwardPropultion: this.navControl.engine2.isForwardPropultion,
requestedPower: this.controls.throttle2,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine2.power.correction,
correctionAngle: this.navControl.engine2.angle.correction
}
};
console.log(params);
this.server.updateEngines(params).pipe(debounceTime(500), distinctUntilChanged()).subscribe(result => {
console.log('HttpClient [POST] /api/navigation/post', result);
this.procesEngines(result);
}, error => {
console.log(`There was an issue. ${error._body}.`);
});
}
debounceTime 不起作用,所有更改都已提交。
我觉得debounce时间的位置不太对。
也许我的做法是完全错误的。
您必须将所有更改放在单个可观察对象上,然后您可以进行去抖动等操作。
你可以这样做:
private updateQueue = new Subject();
private updateQueueSubscription = null;
ngOnInit() {
this.updateQueueSubscription = this.updateQueue
.pipe(
debounceTime(500),
distinctUntilChanged(isEqual), // from lodash
mergeMap(params => this.server.updateEngines(params))
)
.subscribe(
(result) => {
console.log('HttpClient [POST] /api/navigation/post', result);
this.procesEngines(result);
},
error => {
console.log(`There was an issue. ${error._body}.`);
},
)
}
ngOnDestroy() {
this.updateQueueSubscription.unsubscribe();
}
public updateNavControl(): void {
let params: INavigationRequest = {
engine1: {
id: this.navControl.engine1.id,
isForwardPropultion: this.navControl.engine1.isForwardPropultion,
requestedPower: this.controls.throttle1,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine1.power.correction,
correctionAngle: this.navControl.engine1.angle.correction
},
engine2: {
id: this.navControl.engine2.id,
isForwardPropultion: this.navControl.engine2.isForwardPropultion,
requestedPower: this.controls.throttle2,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine2.power.correction,
correctionAngle: this.navControl.engine2.angle.correction
}
};
console.log(params);
this.updateQueue.next(params);
}
updateQueue
将是一个主题,您可以在其中发送所有更改,您可以对它们进行反跳并使用 distinctUntilChanged
。
另请注意:您的代码中的 distinctUntilChanged
将不起作用,因为它不会进行深入比较 - 为此,您将需要例如来自 Lodash 的 isEqual 函数。
在我的 Angular 6 项目中,我有一个包含 3 个范围输入和 1 个复选框的组件。 使用复选框,我可以 link 3 个范围输入中的 2 个的值,这样如果一个被更改,另一个也会相应地更改。 当复选框未选中时,第二个不会更新。 当其中一个范围输入发生变化时,所有 3 个控件的值都必须发送到 API.
到目前为止我是成功的。 问题是,当我更改范围输入时,会有 post 对 API 的突发请求。 我想减少请求的爆发。
在模板中我有以下控件:
<input class="my-custom-range" type="range" [min]="-1 * navControl.engine1.power.max" [max]="navControl.engine1.power.max" [(ngModel)]="controls.throttle1" (ngModelChange)="onChangeThrothel1($event)" [disabled]="!navControl.engine1.isOnline" >
<input class="my-custom-range" type="range" [min]="-1 * navControl.engine2.power.max" [max]="navControl.engine2.power.max" [(ngModel)]="controls.throttle2" (ngModelChange)="onChangeThrothel2($event)" [disabled]="!navControl.engine2.isOnline" >
<mat-slider min="-80" max="80" step="8" thumbLabel="true" vertical="true" [(ngModel)]="controls.mainHelm" (ngModelChange)="changeMainHelm($event)" [disabled]="!navControl.engine1.isOnline" style="margin-top: 4em; height: 100%"></mat-slider>
<mat-checkbox [(ngModel)]="syncEngines">Motor Sync</mat-checkbox>
我有一些接口是这样的:
export interface INavigationRequest {
engine1: IEngineRequest;
engine2: IEngineRequest;
}
export interface IEngineRequest {
id: number;
requestedPower: number;
isForwardPropultion: boolean;
requestedAngle: number;
correctionPower: number;
correctionAngle: number;
}
在 server.service.ts 我有以下内容:
updateEngines(params: INavigationRequest): Observable<INavigationResponse> {
console.log('update engines', params);
return this.http.post<INavigationResponse>(`${this.baseUrl}/api/navigation/post/`, params);
}
在 component.ts 我有以下内容:
public onChangeThrothel1(value): void {
if (value && this.syncEngines) {
this.controls.throttle2 = value;
}
console.log('1', this.controls.throttle1);
console.log('2', this.controls.throttle2);
this.updateNavControl();
}
public onChangeThrothel2(value): void {
if (value && this.syncEngines) {
this.controls.throttle1 = value;
}
console.log('1', this.controls.throttle1);
console.log('2', this.controls.throttle2);
this.updateNavControl();
}
public changeMainHelm(value): void {
if (value) {
this.controls.helm = value;
this.updateNavControl();
}
}
public updateNavControl(): void {
let params: INavigationRequest = {
engine1: {
id: this.navControl.engine1.id,
isForwardPropultion: this.navControl.engine1.isForwardPropultion,
requestedPower: this.controls.throttle1,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine1.power.correction,
correctionAngle: this.navControl.engine1.angle.correction
},
engine2: {
id: this.navControl.engine2.id,
isForwardPropultion: this.navControl.engine2.isForwardPropultion,
requestedPower: this.controls.throttle2,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine2.power.correction,
correctionAngle: this.navControl.engine2.angle.correction
}
};
console.log(params);
this.server.updateEngines(params).pipe(debounceTime(500), distinctUntilChanged()).subscribe(result => {
console.log('HttpClient [POST] /api/navigation/post', result);
this.procesEngines(result);
}, error => {
console.log(`There was an issue. ${error._body}.`);
});
}
debounceTime 不起作用,所有更改都已提交。
我觉得debounce时间的位置不太对。 也许我的做法是完全错误的。
您必须将所有更改放在单个可观察对象上,然后您可以进行去抖动等操作。
你可以这样做:
private updateQueue = new Subject();
private updateQueueSubscription = null;
ngOnInit() {
this.updateQueueSubscription = this.updateQueue
.pipe(
debounceTime(500),
distinctUntilChanged(isEqual), // from lodash
mergeMap(params => this.server.updateEngines(params))
)
.subscribe(
(result) => {
console.log('HttpClient [POST] /api/navigation/post', result);
this.procesEngines(result);
},
error => {
console.log(`There was an issue. ${error._body}.`);
},
)
}
ngOnDestroy() {
this.updateQueueSubscription.unsubscribe();
}
public updateNavControl(): void {
let params: INavigationRequest = {
engine1: {
id: this.navControl.engine1.id,
isForwardPropultion: this.navControl.engine1.isForwardPropultion,
requestedPower: this.controls.throttle1,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine1.power.correction,
correctionAngle: this.navControl.engine1.angle.correction
},
engine2: {
id: this.navControl.engine2.id,
isForwardPropultion: this.navControl.engine2.isForwardPropultion,
requestedPower: this.controls.throttle2,
requestedAngle: this.controls.helm,
correctionPower: this.navControl.engine2.power.correction,
correctionAngle: this.navControl.engine2.angle.correction
}
};
console.log(params);
this.updateQueue.next(params);
}
updateQueue
将是一个主题,您可以在其中发送所有更改,您可以对它们进行反跳并使用 distinctUntilChanged
。
另请注意:您的代码中的 distinctUntilChanged
将不起作用,因为它不会进行深入比较 - 为此,您将需要例如来自 Lodash 的 isEqual 函数。