【问题标题】:Post values from multiple range inputs on change in Angular 6 with debounceTime使用 debounceTime 在 Angular 6 中更改来自多个范围输入的值
【发布时间】:2018-08-19 15:31:55
【问题描述】:

在我的 Angular 6 项目中,我有一个包含 3 个范围输入和 1 个复选框的组件。 使用复选框,我可以链接 3 个范围输入中的 2 个的值,以便如果一个被更改,另一个会相应地更改。 当复选框未选中时,第二个不会更新。 当更改范围输入之一时,所有 3 个控件的值都必须发送到 API。

到目前为止,我是成功的。 问题是,当我更改范围输入时,会向 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 不起作用,所有更改都已提交。

我认为去抖时间的放置位置不对。 也许我的方法完全错误。

【问题讨论】:

    标签: rxjs angular6 rxjs6


    【解决方案1】:

    您必须将所有更改放在单个 observable 上,然后您可以进行去抖动等操作。

    你可以这样做:

    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 函数。

    【讨论】:

    • 这对我有用 :) 我不得不删除 updateEngines 中参数的输入,但它就像一个魅力
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    相关资源
    最近更新 更多