【问题标题】:Angular/RxJS - Delay stream until previous stream finishedAngular/RxJS - 延迟流直到前一个流完成
【发布时间】:2019-02-24 11:35:41
【问题描述】:

我正在构建一个通知组件,它应该向用户显示通知。当一次创建多个通知时,它应该将它们排队。

现在它可以很好地显示第一个通知,但之后它会同时触发 2 个通知(请参阅下面的当前输出)。它不会等待上一个通知显示然后在显示下一个通知之前再次隐藏。

notifications.api.ts

public notifications = new Subject<INotificationEvent>();
public notifications$ = this.notifications.asObservable();

notifications.component.ts

private finished = new Subject();

constructor(private notifications: NotificationsApi) {}

zip(this.notificationsApi.notifications$, this.notificationsApi.notifications, (i, s) => s).pipe(
  tap(() => {

    if (!this.isActive) {
      this.finished.next();
    }
  }),
  delayWhen(() => this.finished),
  delay(450),
  tap((event: INotificationEvent) => {
    this.notification = event;
    this.isActive = true;
    this.cd.markForCheck();
    console.log(this.notification);
    console.log('showing');
  }),
  delay(this.hideAfter),
  tap(() => {
    this.isActive = false;
    this.cd.markForCheck();
    console.log('closing');
  }),
  delay(450)
).subscribe(() => {
  console.log('finishing');
  this.finished.next();
});

app.component.ts

let i = 0;
setInterval(() => {
  this.notifications.newNotification({message: `${i}`, theme: 'primary'});
  i++;
}, 2000);

电流输出

{message: "0", theme: "primary"}
showing
closing
finishing
{message: "1", theme: "primary"}
showing
{message: "2", theme: "primary"}
showing
closing
finishing
{message: "3", theme: "primary"}
showing
{message: "4", theme: "primary"}
showing
closing
closing
finishing
finishing
{message: "5", theme: "primary"}
showing
{message: "6", theme: "primary"}

期望的输出

{message: "0", theme: "primary"}
showing
closing
finishing
{message: "1", theme: "primary"}
showing
closing
finishing
{message: "2", theme: "primary"}
showing
closing
finishing
{message: "3", theme: "primary"}
showing
closing
finishing
{message: "4", theme: "primary"}
showing
closing
finishing
{message: "5", theme: "primary"}
showing
closing
finishing
{message: "6", theme: "primary"}
showing
closing
finishing

我该如何解决这个问题?

【问题讨论】:

  • 所以你想为450ms 显示一个通知然后隐藏它并在有任何排队时显示另一个?
  • @martin 每个通知总共显示 3900 毫秒,450 毫秒是隐藏/显示的动画,然后在 3000 毫秒内可见。

标签: angular rxjs angular-services rxjs-pipeable-operators


【解决方案1】:

根据您的描述,在我看来,您可以使用concatMapdelay 轻松实现同样的目标。

在这个例子中,每一次按钮点击都代表一个通知。每个通知需要 2 秒。这取决于你想在观察者中做什么,但如果你根本不需要通知,你可以把它留空(否则你可能需要startWith)。多个通知在concatMap 中排队并一个接一个地执行。

const notification$ = fromEvent(document.getElementsByTagName('button')[0], 'click');

notification$.pipe(
  concatMap(event => of(event).pipe(
    tap(v => console.log('showing', v)),
    delay(2000),
    tap(v => console.log('closing', v)),
  ))
).subscribe();

现场演示:https://stackblitz.com/edit/rxjs-nqtfzm?file=index.ts

【讨论】:

  • 如此优雅的解决方案!完美运行:D 还必须将服务中的主题类型更改为ReplaySubject,以便它会接收对服务的过早调用。非常感谢!
猜你喜欢
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多