Angular / RxJS-将流延迟到上一个流完成

时间:2019-02-24 11:35:42

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

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

现在,它可以很好地显示第一个通知,但之后它会同时触发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

我该如何解决?

1 个答案:

答案 0 :(得分:2)

根据您的描述,在我看来,@PostConstruct concatMap可以轻松实现相同目标。

在此示例中,每次单击按钮都代表一个通知。每个通知需要2秒。这取决于您要在观察者中执行的操作,但是如果您根本不需要该通知,则可以将其留空(否则可能需要delay)。多条通知在startWith中排队,并一个接一个地执行。

concatMap

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