RxJS - 管理过期的可观察数组

时间:2018-01-03 16:26:51

标签: rxjs

我正在尝试实现通知小部件。 每隔一段时间,一条消息(一个“toast”)将显示在浏览器窗口的一角。 我希望在30秒后自动隐藏消息。 我还想要的是,如果同时有更多消息到达,小部件将在堆栈中显示每个消息,逐步隐藏过期消息。

我可以用setTimeout实现所有内容,但我非常确定RxJS可以使用更好的方法,而且我发现文档很难导航。 (我正在努力与http://reactivex.io/documentation/operators.htmlhttp://rxmarbles.com/,博客文章等等)

有没有人知道一个或多个有助于满足要求的运营商?

谢谢!

编辑:示例时间轴

0 - empty window
1 - show "A"
5 - show "B" (A and B are both shown)
29 -  show "C" (A, B and C are stacked)
31 - A disappears (only B and C remain)
35 - B disappears (C shown)
59 - C disappears

2 个答案:

答案 0 :(得分:2)

您可以使用主题作为队列将烤面包机推向它。 delay()可让您调整烤面包机停留在屏幕上的持续时间

let a=Rx.Observable.of('a')
let b=Rx.Observable.of('b')
let c=Rx.Observable.of('c')

let queue=new Rx.Subject()


queue.mergeMap(res=>res)
.do(res=>{
// you can make toast appear now
console.log(res,':appearing')
})
.delay(2000)
.do(res=>{
// you can make toast disappear now
console.log(res,':disappearing')
}).subscribe()

setTimeout(()=>queue.next(a))
setTimeout(()=>queue.next(b),2000)
setTimeout(()=>queue.next(c),4000)

https://jsfiddle.net/7jcsLd4o/

答案 1 :(得分:0)

最后我找到了我想要的那种运算符:scan运算符(文档herehere)。

我的实现基于Subject发出“隐藏”和“显示”事件,以及BehaviourSubject将事件累积到数组上。

与RxJS相关的元素如下:

export class Message {
  id: string;
  text: string;
  type: MessageType;
}

export class MessageAction {
  action: 'show' | 'hide';
  msg: Message;
}

...
export class NotificationComponent {
...

  messages = new BehaviorSubject<Message[]>([]);
  msgsSource = new Subject<MessageAction>();


  constructor() {
    this.msgsSource.scan((arr: Message[], msgAction: MessageAction) => {
      return (msgAction.action === 'show') ?
        arr.concat(msgAction.msg) :
        arr.filter(msg => msg.id !== msgAction.msg.id);
    }, []).subscribe(this.messages);
  }

  show(text: string, type: MessageType, autoHideAfter: number = DEFAULT_MESSAGE_TIMEOUT) {
    const msg: Message = {
      id: '' + (this.msgIdx++),
      text: text,
      type: type
    };

    this.msgsSource.next({ action: 'show', msg: msg });
    setTimeout(() => {
      this.msgsSource.next({ action: 'hide', msg: msg });
    }, autoHideAfter);
  }

  hide(id: string) {
    this.msgsSource.next({ action: 'hide', msg: { id: id } as Message });
  }

...
}