Angular 角度材质快捷键:不使用新消息覆盖以前的消息

Angular 角度材质快捷键:不使用新消息覆盖以前的消息,angular,angular-material,angular7,Angular,Angular Material,Angular7,我使用Snackbar向用户显示错误和警告消息。有时,这些事件可能在时间上彼此接近,比第一条消息的显示持续时间更近。如此接近,以至于在用第二条消息覆盖之前,用户没有足够的时间阅读第一条消息 是否有办法将行为更改为在显示第二条消息之前等待第一条消息的结束,或将它们堆积起来?您可以将所有消息放入一个数组中,以模拟消息的“队列”,而不是为每条消息调用Snackbar。我建议有一个服务负责处理这个问题 然后,在此服务中,您可以订阅Snackbar的afterdisembled()回调,该回调将在Snac

我使用Snackbar向用户显示错误和警告消息。有时,这些事件可能在时间上彼此接近,比第一条消息的显示持续时间更近。如此接近,以至于在用第二条消息覆盖之前,用户没有足够的时间阅读第一条消息


是否有办法将行为更改为在显示第二条消息之前等待第一条消息的结束,或将它们堆积起来?

您可以将所有消息放入一个数组中,以模拟消息的“队列”,而不是为每条消息调用Snackbar。我建议有一个服务负责处理这个问题

然后,在此服务中,您可以订阅Snackbar的
afterdisembled()
回调,该回调将在Snackbar关闭时触发。下面是一个简单的示例,展示了它的样子:

messageQueue: string[] = [
'Message 1',
'Message 2',
'Message 3'
]

private displaySnackbar(): void {
  const nextMessage = this.getNextMessage();

  if(!nextMessage){
    return;
  }

  this.snackBar.open(nextMessage, undefined, { duration: 1000 })
  .afterDismissed()
  .subscribe(() => {
    this.displaySnackbar();
  });
}

private getNextMessage(): string | undefined {
  return this.messageQueue.length ? this.messageQueue.shift() : undefined;
}
编辑:

为了避免任何混淆,在我提供的示例中,我不建议直接调用
displaySnackbar()
(因此是
private
可见性范围)。取而代之的是,我是如何将其公开的(正如您在下面的Stackblitz演示中所看到的):

这仅仅取决于
processingMessage
标志来确定它是否应该调用
displaySnackbar()
方法。当然,我们还需要设置此标志,因此这里是更新的
displaySnackbar()

是Stackblitz的基本演示


在演示中,您将看到,您可以“垃圾邮件”单击“添加邮件”按钮,该按钮将对创建的所有邮件进行排队,但Snackbar仅在每条邮件显示完1秒后才会显示这些邮件。

感谢您提供的工作示例,我确实在考虑将所有这些打包到它自己的服务中,因为我预见到在未来的项目中重用它们。再次感谢。这真的有效吗?您何时开始第一次触发通知?你不是每次都在初始化订阅吗?在这种配置中,这不可能在生产中正常工作。是的,它确实有效,文章中的Stackblitz示例应该说明这一点。
afterdiscomered
订阅是一次性可观察的(类似于http
get
),因此在事件发生后不会留下订阅。“在这种配置中,这是不可能工作的……”到底是怎么回事?
addMessage(message: string): void {
  this.messageQueue.push(message);

  if(!this.processingMessage) {
    this.displaySnackbar();
  }
}
private displaySnackbar(): void {
  const nextMessage = this.getNextMessage();

  if(!nextMessage){
    this.processingMessage = false; // No message in the queue, set flag false
    return;
  }

  this.processingMessage = true; // A message was dequeued and is being processed

  this.snackBar.open(nextMessage, undefined, { duration: 1000 })
  .afterDismissed()
  .subscribe(() => {
    this.displaySnackbar();
  });
}