首页 > 解决方案 > 重复定时动作的正确设计

问题描述

语境

我正在创建一个页面,您可以在给定时间设置一些警报,并且它们是可重复的(假设您希望它在上午 10:00 响起,它将在每天上午 10:00 响起)。

该功能必须:

问题

我尝试了许多使用 RxJS 进行建模的方法,但由于我的需要,这些设计总是存在重大缺陷。这是我尝试过的,以及失败的原因:

总的来说,问题是糟糕的设计,我找不到实现这种行为的正确方法,主要是因为我想避免每秒调用一个方法,但另一方面我似乎找不到另一种方法这样做,可能是因为我对这个解决方案持封闭态度,这就是我在这里的原因。

标签: angularrxjsngrx

解决方案


首先,我将创建一个可以自行调度并包含其状态的 Alarm 类:

class Alarm {
  public lastRangTime = 0;
  private stopper = new Subject<void>();

  get hasRang() {
    return this.lastRangTime > 0;
  }

  get remaining() {
    return this.ringTime - Date.now();
  }

  // add more metadata

  constructor(public ringTime: number, public interval: number) {}

  start(): Observable<number> {
    return timer(this.ringTime - Date.now(), this.interval)
      .pipe(
        tap(() => {
          this.lastRangTime = this.ringTime;
          this.ringTime += this.interval;
        }),
        takeUntil(this.stopper)
      )
  }

  stop() {
    this.stopper.next();
  }
}

还有一些容器/服务来保存所有订阅:

class AlarmScheduler {
  private queue = new Subject<Alarm>();
  private subscription: Subscription = null;

  schedule(ringTime: number, interval: number = DEFAULT_INTERVAL) {
    const alarm = new Alarm(ringTime, interval);

    this.queue.next(alarm);

    return alarm;
  }

  initialize() {
    this.subscription = this.queue
      .pipe(mergeMap(alarm => alarm.start()))
      .subscribe();
  }

  destroy() {
    this.subscription.unsubscribe();
  }
}

比您可以简单地从AlarmScheduler. 他们将以给定的间隔重复自己。

const scheduler = new AlarmScheduler();

scheduler.initialize();

const a1 = scheduler.schedule(Date.now() + 5000);
const a2 = scheduler.schedule(Date.now() + 10000);

工作示例:https ://stackblitz.com/edit/typescript-uft7up

当然,您必须制定一些细节,但就安排警报而言,我希望上面的代码足以让您入门。


推荐阅读