我如何使用iif()运算符正确实现条件debounceTime()运算符?

问题描述 投票:0回答:1

我有一个BehaviourSubject,可通过Service的构造函数中的getSaveBehaviorSubject()进行订阅。此行为主题可以从其他组件/服务接收多种类型的数据,其中某些类型的数据需要存储在后端而其他人则没有。当它接收到确实需要存储的值时,它将通过put/post请求将其发送到后端。作为请求速率限制器,我使用debounce(300)运算符,以便在经过300毫秒的不活动时间后才向服务器发出实际请求。这将防止服务器抛出429 Too many requests错误。仅当需要存储的值类型被推送时,才应应用反跳操作符。我尝试使用iif()运算符创建这样的条件。我的代码如下:

this.myService.getSaveBehaviorSubject()
.pipe(
  tap(pair => {
    if(this.dataStoreServiceJustInitialized){
      this.dataStoreServiceJustInitialized = false; 
      return;
    }

    if (pair.length > 1){
        this.updateDataTypeValue(pair);
        localStorage.setItem(pair[0], JSON.stringify(pair[1]));
        if(pair[0] === DataType.MEASURE_SYSTEM_PREFERENCE)
            this.adjustSearchRadiusToChangedMeasureSystem();
    }
  }),
  mergeMap(pair =>
    iif(() => !!(this.loggedInSubject.value && this.dataTypeExclusionList.includes(pair[0])), 
    of(pair).pipe(debounceTime(2000)), of(pair)
    )))
.subscribe(pair => {If (this.loggedInSubject.value) // make request to server...}

我的解决方案基于本教程:https://www.learnrxjs.io/learn-rxjs/operators/conditional/iif,感兴趣的代码从mergeMap开始。

如果用户登录,并且数据类型应保存到数据库中(dataTypeExclusionList中不包含),则iif()应该使用包含debounceTime运算符的管道返回一个可观察对象。否则,它应该只返回一个具有原始值的新observable。

iif条件为true时,debounceTime似乎不起作用。无论我是否登录,或者是否应该保存数据类型,它都将立即发送请求。显然我做错了。

谁能告诉我将iif运算符与debounceTime运算符结合使用的正确方法是什么?谢谢

angular rxjs rxjs6 iif
1个回答
0
投票

这里有两个问题:

  1. debounce将在完成时立即发出当前值-无需等待超时。 of工厂将发出一个通知,然后立即完成。因此,没有延迟。您可以通过将debounceTime替换为delay来解决此问题。

  2. 您正在使用mergeMap,当它收到新的通知时,它不会从先前的Observable退订。因此,您可能会遇到getSaveBehaviorSubject在超时时间内发出100次并发送100个服务器请求的情况。您可以通过将mergeMap替换为switchMap来解决此问题。

同时应用这两个都可以解决您的问题。

但是,我建议使用另一种方法:使用debounce运算符。传递一个返回Observable的函数,而不是超时值。当此Observable发出时,将转发当前值。

喜欢这个:

this.myService.getSaveBehaviorSubject().pipe(
  tap(...),
  debounce(pair => {
    if(... debounce condition ...) {
      return timer(2000);
    } else {
      return timer(0);
    }
  }
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.