如何使用 Rxjs 订阅日期变化

How to subscribe to date chage with Rxjs

我找不到一个使用 Rxjs 的“简单”示例,演示了我们如何将天数变化作为一个事件来监听。

例如,假设每次进入新的一天我都必须执行某些方法。我怎样才能用反应范式来处理这个问题并订阅时间事件?

只需使用 timer();interval() Observable,它可以在您想要的任何时间间隔发射,并在当天的每次发射检查中发射。 F.ex。这将每秒检查当天:

timer(0, 1000).pipe(
  tap(() => {
    const date = new Date();
    const currentDay = date.getDate();
  })
)

每秒检查当前日期没有多大意义,但当前时间可能比第二天早一秒,因此可能需要。为了改善这一点,您可以在日期更改时切换到新的 Observable,它将在 23 小时 59 分钟后发出:

const source$ = timer(0, 1000).pipe(
  switchMap(() => {
    const dayState = this.getDayState();

    if (dayState && dayState.ends) {
      return timer(0, (1000 * 60 * 60 * 23) + (1000 * 60 * 59)).pipe(
        switchMap(() => this.source$)
      )
    } 
    return this.source$;
  })
)

function getDayState(): {stars?: boolean, ends?: boolean} {
  const date = new Date();
  const hours = date.getHours();
  const minutes = date.getMinutes();

  if (hours === 23 && minutes === 59) {
    return { ends: true };
  } else if (hours === 0 && minutes === 1) {
    return { starts: true };
  }
}

这是一个非常粗略的例子。另外,目前我不知道浏览器将如何处理这个长期订阅。您可能需要采取一些变通办法,例如强制重新加载浏览器或添加其他检查,以便您可以依赖此流。此外,不使用 getDayState() 函数,更可靠的方法是存储最后一天并检查当前日期是否不同。

我已经通过创建一个延迟到订阅发生的可观察对象解决了这个问题,然后计算时间并寻找最近的午夜来发出事件。

function newSolarDayObserver() {
    return defer(() => {
      const timeAtSubscription = new Date();
      const nextDay = new Date();
      // get the nearest midnight in future
      nextDay.setHours(24, 0, 0, 0);
      const initialDelay = nextDay.getTime() - timeAtSubscription.getTime();
      // repeat every 24 hours and 1 minute
      const repeat = 1000 * 60 * 61 * 24;
      return timer(initialDelay, repeat);
    });
  }

然后可以将此可观察对象与 reapeatWhen 运算符一起使用,以在发出新的一天事件时重复之前的流。