将非标准调度程序传递给操作员

时间:2015-09-30 19:02:01

标签: javascript rxjs

让我们说我想将调度程序传递给RxJS运算符,使其每5秒发出一次通知。当然,只需使用interval或其他现有运算符即可轻松完成。但如果我真的想用一个调度程序来完成它,我该怎么做呢?

我的第一个想法是继承Rx.Scheduler.default。这会是要走的路吗?如果是这样,该子类怎么样?同样,我理解这是一种复杂的方法来完成使用操作符的简单方法,但我只是对自定义调度程序感到好奇。

2 个答案:

答案 0 :(得分:4)

操作应始终独立于用于实现它们的调度程序。调度员只知道一件事,时间。每个调度程序都专门用于处理自己的时间概念。它们明确地构建来处理特定的运营商,因为这将是一个关注的混合。

因此,对于您创建定期任务的既定目标,我不建议您尝试实际创建自己的调度程序,但根本不需要。调度程序带有一个已经支持此功能的接口。

您可以使用schedulePeriodicscheduleRecursiveFuture来完成此操作。

//Using periodic
Rx.Observable.interval = function(period, scheduler) {

  return Rx.Observable.create(function(observer) {
    return scheduler.schedulePeriodic(0, period, function(count) {
      observer.onNext(count);
      return count + 1;
    });
  });

};

//Using scheduleRecursive
Rx.Observable.interval = function(period, scheduler) {

  return Rx.Observable.create(function(observer) {
    return scheduler.scheduleRecursiveFuture(0, period, function(count, self) {
      observer.onNext(count);
      self(period, count + 1); 
    });
  });
};

Reference 1Reference 2;

前者应该更容易包围,基本上只是根据周期参数安排在时间上重复间隔发生的事情。

后者通常有点难以解释,但实质上你是在安排一项任务,然后在执行该任务的某个时候,你重新安排它(这就是{{1} }参数)正在做。这允许您使用period参数获得相同的效果。

这项工作的时间直接受到您决定传入运营商的调度程序的影响。例如,如果您传入self,它将尝试使用最佳方法进行异步完成,无论是defaultsetTimeout还是其他一些我不记得的事情。如果你传入一个setIntervalTestScheduler,那么在递增每个时钟之前实际上不会做任何事情,但这样做可以很好地控制时间流量。

tl; dr 如果你有一些新的总体时间概念表达,那么只能实现新的HistoricalScheduler,否则使用现有的API来处理Scheduler最好的Scheduler符合你想要时间的方式。

答案 1 :(得分:1)

你应该自己动手吗?

明白:不会。很可能你可以完成现有操作员所需的工作。像bufferwindowsample等等。调度程序开发并不是完全简单。

如何滚动自己的RxJS 4 Scheduler

如果您想要在RxJS 4中实现自己的调度程序,那么您将继承Rx.Scheduler,然后覆盖每个调度方法:schedulescheduleFuture,{{1} },schedulePeriodicscheduleRecursive ...您也可能希望覆盖scheduleRecursiveFuture以返回与您的日程安排相关的内容。

Here is an example of a custom scheduler that uses button clicks inside of real time

now

如何在RxJS 5(alpha)中执行此操作

计划在RxJS 5中再次更改,因为该版本是从头开始重写的。

在RxJS5中,您可以创建任何符合以下界面的对象:

/**
NOTE: This is REALLY fast example. There is a lot that goes into implementing a 
Scheduler in RxJS, for example what would `now()` do in the scheduler below? It's also missing a number of scheduling methods.
*/

class ButtonScheduler extends Rx.Scheduler {
  /** 
    @param {string} the selector for the button (ex "#myButton")
  */
  constructor(selector) {
    super();
    this.button = document.querySelector(selector);
  }

  schedule(state, action) {
    const handler = (e) => {
      action(state);
    };
    const button = this.button;

    // next click the action will fire
    button.addEventListener('click', handler);

    return {
      dispose() {
        // ... unless you dispose of it
        button.removeEventListener('click', handler);
      }
    };
  }

  // Observable.interval uses schedulePeriodic
  schedulePeriodic(state, interval, action) {
    const button = this.button;

    let i = 0;
    const handler = (e) => {
      const count = i++;
      if(count > 0 && count % interval === 0) {
        state = action(state);
      }
    };

    // next click the action will fire
    button.addEventListener('click', handler);

    return {
      dispose() {
        // ... unless you dispose of it
        button.removeEventListener('click', handler);
      }
    };
  }
}

Rx.Observable.interval(1, new ButtonScheduler('#go'))
  .subscribe(x => {
    const output = document.querySelector('#output');
    output.innerText += x + '\n';
  });

其中interface Scheduler { now(): number schedule(action: function, delay: number = 0, state?: any): Subscription } 只是具有Subscription功能的任何对象(与unsubscribe相同,真的)

但是,除非完全有必要,否则我不建议创建一个调度程序。

我真的希望这有助于回答你的问题。