Angular 角度/RxJS-延迟流直到上一个流完成
我正在构建一个通知组件,它应该向用户显示通知。当一次创建多个通知时,它应该对它们进行排队 现在它只显示第一个通知,但之后它会同时触发两个通知(请参见下面的当前输出)。它不会等待上一个通知显示,然后在显示下一个通知之前再次隐藏 通知.api.ts:Angular 角度/RxJS-延迟流直到上一个流完成,angular,rxjs,angular-services,rxjs-pipeable-operators,Angular,Rxjs,Angular Services,Rxjs Pipeable Operators,我正在构建一个通知组件,它应该向用户显示通知。当一次创建多个通知时,它应该对它们进行排队 现在它只显示第一个通知,但之后它会同时触发两个通知(请参见下面的当前输出)。它不会等待上一个通知显示,然后在显示下一个通知之前再次隐藏 通知.api.ts: public notifications = new Subject<INotificationEvent>(); public notifications$ = this.notifications.asObservable(); pr
public notifications = new Subject<INotificationEvent>();
public notifications$ = this.notifications.asObservable();
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();
});
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
应用程序组件.ts:
public notifications = new Subject<INotificationEvent>();
public notifications$ = this.notifications.asObservable();
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();
});
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
电流输出:
public notifications = new Subject<INotificationEvent>();
public notifications$ = this.notifications.asObservable();
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();
});
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
所需输出:
public notifications = new Subject<INotificationEvent>();
public notifications$ = this.notifications.asObservable();
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();
});
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
如何解决这个问题?根据您的描述,在我看来,您可以通过
concatMap
和delay
轻松实现同样的效果
在本例中,每次单击按钮表示一次通知。每次通知需要2秒。这取决于您想在observer中执行什么操作,但如果您根本不需要通知,则可以将其保留为空(否则您可能需要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();
现场演示:根据您的描述,在我看来,您可以通过
concatMap
和delay
轻松实现同样的效果
在本例中,每次单击按钮表示一次通知。每次通知需要2秒。这取决于您想在observer中执行什么操作,但如果您根本不需要通知,则可以将其保留为空(否则您可能需要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();
现场演示:所以你想在
450毫秒内显示一个通知,然后隐藏它,如果有排队的话,再显示另一个通知?@martin每个通知总共显示3900毫秒,450ms是“隐藏/显示”的动画,然后它在3000ms的时间内可见。因此,您希望为450ms
显示一个通知,然后将其隐藏并显示另一个通知(如果有任何排队?@martin每个通知总共显示3900ms,450ms是隐藏/显示的动画,然后再加上3000ms它是可见的。这是一个多么优雅的解决方案!工作非常完美:D还必须将服务中的主题类型更改为ReplaySubject
,这样它就可以接收对服务的过早调用。非常感谢!如此优雅的解决方案!工作非常完美:D还必须将服务中的主题类型更改为ReplaySubject
,这样它就可以接收对服务的过早调用。非常感谢!