Javascript RxJS:延迟传入的观测值

Javascript RxJS:延迟传入的观测值,javascript,angular,typescript,rxjs,observable,Javascript,Angular,Typescript,Rxjs,Observable,我有一个Snackbar组件,它负责为用户显示带有信息的Snackbar。通知来自我在SnackbarComponent中订阅的NotificationService。传入消息被推送到消息数组中,并在3秒钟后从该数组中移出。在我的html模板中,我迭代消息并显示它们 export class SnackbarComponent implements OnInit, OnDestroy { private notificationSubscription: Subscription; me

我有一个Snackbar组件,它负责为用户显示带有信息的Snackbar。通知来自我在
SnackbarComponent
中订阅的NotificationService。传入消息被推送到消息数组中,并在3秒钟后从该数组中移出。在我的html模板中,我迭代消息并显示它们

export class SnackbarComponent implements OnInit, OnDestroy {
  private notificationSubscription: Subscription;
  messages: NotificationMessage[] = [];

  constructor(private notificationService: NotificationService) {
  }

  ngOnInit() {
    this.notificationSubscription = this.notificationService.notification$
      .subscribe(
        (message: NotificationMessage) => {
          this.messages.push(message);
          setTimeout(() => {
            this.messages.shift();
          }, 3000);
        }
      )
  }

  ngOnDestroy(): void {
    this.notificationSubscription.unsubscribe();
  }
问题是,我希望一次只显示3条消息,而延迟其他消息(如果当前少于3条消息,则立即显示)

我有一个可行的解决方案,如下所示:

private notificationSubscription: Subscription;
messages: NotificationMessage[] = [];
messagesQueue: NotificationMessage[] = [];


  ngOnInit() {
    this.notificationSubscription = this.notificationService.notification$
      .subscribe(
        (message: NotificationMessage) => {
          if (this.messages.length < 3) {
            this.messages.push(message);
            this.timeoutMessage();
          } else {
            this.messagesQueue.push(message);
          }
        }
      )
  }

  private timeoutMessage() {
    setTimeout(() => {
      this.messages.shift();
      if (this.messagesQueue.length > 0) {
        this.messages.push(this.messagesQueue.shift());
        this.timeoutMessage();
      }
    }, 3000);
  }
私人通知订阅:订阅;
消息:NotificationMessage[]=[];
messagesQueue:NotificationMessage[]=[];
恩戈尼尼特(){
this.notificationSubscription=this.notificationService.notification$
.订阅(
(消息:NotificationMessage)=>{
if(this.messages.length<3){
this.messages.push(message);
this.timeoutMessage();
}否则{
this.messagesQueue.push(message);
}
}
)
}
专用超时消息(){
设置超时(()=>{
this.messages.shift();
如果(this.messagesQueue.length>0){
this.messages.push(this.messagesQueue.shift());
this.timeoutMessage();
}
}, 3000);
}
如果有3条或多条消息,则新消息将被推送到messagesQueue,并且在
timeoutMessage()
中,来自
messagesQueue
的对象将被转移到messages数组中


但我觉得这个解决方案并不优雅。有没有一种RxJS方法可以通过一些
管道
操作符以某种方式延迟消息?

您可以使用delay操作符或条件延迟delayWhen根据条件延迟消息

import {delay} from 'rxjs/operators';

this.notificationService.notification$.pipe(
  delay(3000)
).subscribe();
delayWhen

this.notificationService.notification$.pipe(
  delayWhen(message => this.messages.length < 3 ? interval(0) : interval(3000))
).subscribe();
this.notificationService.notification$.pipe(
delayWhen(message=>this.messages.length<3?间隔(0):间隔(3000))
).subscribe();

您可以使用
BufferCount
操作符来执行此操作。它一次将发出3个值,我添加了第二个延迟来确保

import {bufferCount,delay } from 'rxjs/operators';

this.notificationService.notification$.pipe(
  bufferCount(3),delay(3000)
).subscribe();

这里有一个stackblitz:

如果只有一个通知,则在另外两个通知到来之前不会显示。@mlemmy,它将显示。你可以尝试我共享的stackblitz链接。尝试将可观察值更改为1并检查。它会发出它。BufferCount只是对值进行分组。请看:它显示了我在这个解决方案中遇到的问题。另外,我不喜欢它强迫我在订阅中有一个数组,因为它会延迟每个NORITION。如果消息数组长度小于3,我不想延迟它们。并考虑这种情况:3通知同时到来,在2500毫秒第四通知即将到来。将显示3个通知,3000毫秒后这些通知应消失,第4个通知应在3000毫秒时再显示3000毫秒,但第4个通知将在5500毫秒时显示。必须以某种方式计算间隔时间,将其设置为3000将导致订单问题,请看: