【发布时间】:2021-09-25 14:06:16
【问题描述】:
我正在寻找一个 RxJS 运算符(或运算符的组合),它可以让我实现这一目标:
- observable 触发的每个事件都应按其触发顺序进行处理(不得跳过、限制、去抖动任何值)。
- 我应该能够在处理 2 个后续事件之间定义一个设定的时间间隔。
- 如果当前没有处理以前的事件,则应立即处理下一个事件(无延迟)。
我创建了following example,我希望它会更清楚:
import { Component, OnInit } from "@angular/core";
import { Subject } from "rxjs";
import { delay } from "rxjs/operators";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
counter = 1;
displayedValue = 1;
valueEmitter = new Subject<number>();
valueEmitted$ = this.valueEmitter.asObservable();
ngOnInit() {
// I want to allow each incremented value to be displayed for at least 2 seconds
this.valueEmitted$.pipe(delay(2000)).subscribe((value) => {
this.displayedValue = value;
});
}
onClick() {
const nextCounter = ++this.counter;
this.counter = nextCounter;
this.valueEmitter.next(nextCounter);
}
}
在此示例中,我希望在 counter 中增加的每个值都显示为 displayedValue 至少 2 秒。
因此,当用户第一次点击 onClick 时,显示的值应立即从 1 变为 2,但如果用户继续快速增加 counter,displyedValue 应以延迟的方式跟随,允许每个之前增加的数字要显示 2 秒再改变,慢慢赶上当前的计数器值。
这可以通过 RxJs 操作符实现吗?
更新
目前我想出了following solution:
import { Component, OnInit } from "@angular/core";
import { Subject } from "rxjs";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
counter = 1;
displayedValue = 1;
currentDisplayedValueStartTime = 0;
readonly DISPLAY_DURATION = 2000;
valuesToDisplay = [];
displayedValueSwitcherInterval: number | null = null;
valueEmitter = new Subject<number>();
valueEmitted$ = this.valueEmitter.asObservable();
ngOnInit() {
this.valueEmitted$.pipe().subscribe((value) => {
this.handleValueDisplay(value);
});
}
onClick() {
const nextCounter = ++this.counter;
this.counter = nextCounter;
this.valueEmitter.next(nextCounter);
}
handleValueDisplay(value) {
this.valuesToDisplay.push(value);
if (!this.displayedValueSwitcherInterval) {
this.displayedValue = this.valuesToDisplay.shift();
this.displayedValueSwitcherInterval = window.setInterval(() => {
const nextDiplayedValue = this.valuesToDisplay.shift();
if (nextDiplayedValue) {
this.displayedValue = nextDiplayedValue;
} else {
clearInterval(this.displayedValueSwitcherInterval);
this.displayedValueSwitcherInterval = null;
}
}, this.DISPLAY_DURATION);
}
}
}
这不是我想要的,因为它依赖于组件状态和setInterval 来管理通知队列。我希望找到一些更干净、更具声明性的东西,它依赖于 RxJs 操作符来处理我的通知流和它们的间隔队列——但至少我让这个功能完全按照我的意愿工作。仍然愿意接受有关如何使其变得更好的建议。
【问题讨论】:
-
我还是不清楚。特别是#3。给我一些具体的用例。
-
@SerejaBogolubov - 将示例中的点击视为一次(或以非常短的时间间隔)从服务器返回的多个响应,并且您希望为每个响应显示 2 秒的快餐栏消息随后。 #3 - 你不想在显示第一个小吃店之前等待 2 秒。你查看sandbox了吗?
标签: javascript angular typescript rxjs observable