如何使用 debounceTime 但在一定时间后仍触发该功能?

tru*_*k18 5 rxjs signalr angular

TLDR;我想使用 debounceTime 仅在 300 毫秒过去了而没有被调用的情况下执行该函数。同时,如果这个过程需要很长时间,我也希望能够每1分钟触发一次该功能。否则,该功能只会在流程结束时触发。


基本上,我们的系统有一个很长的过程,会向客户端发出大量 SignalR 更新。当我在客户端收到服务器命令时,我将向服务器发送 2 个额外的 HTTP 请求以获取一些信息。这样只要服务器向我发送更新,它就会回击服务器。

debounceTime如果两个命令之间的时间在 300 毫秒内,我正在使用以防止将太多请求发送回服务器。但是有一种用例,即服务器在 1 小时内不断向客户端发送更新。这意味着客户端将在 1 小时和 300 毫秒触发 getItemCount。

export class LeftNavigationComponent implements OnInit, OnDestroy {
    typeACount: number = 0;
    typeBCount: number = 0;    

    constructor(
        private itemService: service.ItemService,        
        private signalR: service.SignalRService) { }

    ngOnInit(): void {
        this.subscriptions = [            
            this.signalR.itemCreated.debounceTime(300).subscribe(item => this.onUpdatingData())]
    }

    onUpdatingData() {
        Promise.all([
            this.itemService.getItemCount(APP_SETTING.TYPE_A),
            this.itemService.getItemCount(APP_SETTING.TYPE_B)])
            .then(response => this.gettingCountDone(response))
    }

    gettingCountDone(response) {
        this.typeACount = <any>response[0];
        this.typeBCount = <any>response[1];        
    }
}
Run Code Online (Sandbox Code Playgroud)

我还是想debounceTime防止向服务器发送太多请求。但是它应该足够智能,可以在收到第一个更新后每例如 1 分钟自动触发一次。有没有人以前有过用例?

Llo*_*iol 2

帕维尔的答案很接近,但如果我很好地理解了这个问题,你想要这个:

ngOnInit(): void {
    const debounced = this.signalR.itemCreated.debounceTime(300).share();
    this.subscriptions = [         
        debounced.subscribe(() => this.onUpdatingData()),
        debounced.switchMap(() => Observable.interval(60000).takeUntil(this.signalR.itemCreated)).subscribe(() => this.onUpdatingData())
    ]
}
Run Code Online (Sandbox Code Playgroud)

当创建的项目之间的时间大于 300 毫秒时,将调用 onUpdatingData() ,此代码将执行以下操作。之后,每次 debounced 发出一个值时,都会创建一个 1 分钟的throttleTime observable。这意味着,如果 debounced 自上次发射后一分钟内没有发射,则将执行 onUpdatingData() ,依此类推。

改进方法是合并可观察量,因为它们来自相同类型并执行相同的函数,例如如下所示:

ngOnInit(): void {
    const debounced = this.signalR.itemCreated.debounceTime(300).share();
    const merged = debounced.switchMap(() => Observable.interval(60000).takeUntil(this.signalR.itemCreated))
    this.subscriptions = [         
      merged.subscribe(() => this.onUpdatingData())
   ]
}
Run Code Online (Sandbox Code Playgroud)

我发布了一个小提琴,显示了工作解决方案。在此小提琴中,事件 mousedown 模拟流 this.signalR.itemCreated。

https://jsfiddle.net/llpujol/e6b6o655/