如何使用 iif() 运算符正确实现条件 debounceTime() 运算符?
How do i correctly implement a conditional debounceTime() operator with the use of the iif() operator?
我有一个 BehaviourSubject
,它是通过 Service
的构造函数中的 getSaveBehaviorSubject() 订阅的。这个 behaviorsubject 可以从其他 components/services 接收多种类型的数据,其中有些类型需要存储在后端,而有些则不需要。当它收到一个确实需要存储的值时,它会通过 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()
应该 return 一个包含管道的可观察对象一个 debounceTime
运算符。否则它应该 return 一个具有原始值的新观察值。
当 iif
条件为真时,debounceTime 似乎不起作用。无论我是否登录或是否应保存数据类型,它总是会立即发送请求。显然我做错了什么。
谁能告诉我结合使用 iif 运算符和 debounceTime 运算符的正确方法是什么?谢谢
这里有两个问题:
debounceTime
将在其源完成时立即发出其当前值 - 无需等待超时。 of
工厂将生成一个通知,然后立即完成。因此,不会发生去抖动。您可以通过将 debounceTime
替换为 delay
来解决此问题,因为即使源已经完成,它也会等待发出。
您正在使用mergeMap
,它不会在收到新通知时取消订阅之前的Observable。因此,您可能会遇到 getSaveBehaviorSubject
在超时内发出 100 次并且您将发送 100 个服务器请求的情况。您可以通过将 mergeMap
替换为 switchMap
.
来解决此问题
应用两者应该可以解决您的问题。
但是,我会推荐一种不同的方法:使用 debounce
运算符。您传入一个 returns Observable 的函数,而不是超时值。当这个 Observable 发射时,当前值将被转发。
像这样:
this.myService.getSaveBehaviorSubject().pipe(
tap(...),
debounce(pair => {
if(... debounce condition ...) {
return timer(2000);
} else {
return timer(0);
}
}
}
我有一个 BehaviourSubject
,它是通过 Service
的构造函数中的 getSaveBehaviorSubject() 订阅的。这个 behaviorsubject 可以从其他 components/services 接收多种类型的数据,其中有些类型需要存储在后端,而有些则不需要。当它收到一个确实需要存储的值时,它会通过 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()
应该 return 一个包含管道的可观察对象一个 debounceTime
运算符。否则它应该 return 一个具有原始值的新观察值。
当 iif
条件为真时,debounceTime 似乎不起作用。无论我是否登录或是否应保存数据类型,它总是会立即发送请求。显然我做错了什么。
谁能告诉我结合使用 iif 运算符和 debounceTime 运算符的正确方法是什么?谢谢
这里有两个问题:
debounceTime
将在其源完成时立即发出其当前值 - 无需等待超时。of
工厂将生成一个通知,然后立即完成。因此,不会发生去抖动。您可以通过将debounceTime
替换为delay
来解决此问题,因为即使源已经完成,它也会等待发出。您正在使用
mergeMap
,它不会在收到新通知时取消订阅之前的Observable。因此,您可能会遇到getSaveBehaviorSubject
在超时内发出 100 次并且您将发送 100 个服务器请求的情况。您可以通过将mergeMap
替换为switchMap
. 来解决此问题
应用两者应该可以解决您的问题。
但是,我会推荐一种不同的方法:使用 debounce
运算符。您传入一个 returns Observable 的函数,而不是超时值。当这个 Observable 发射时,当前值将被转发。
像这样:
this.myService.getSaveBehaviorSubject().pipe(
tap(...),
debounce(pair => {
if(... debounce condition ...) {
return timer(2000);
} else {
return timer(0);
}
}
}