简体   繁体   English

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

[英]Passing a non-standard Scheduler to an operator

Let's say that I want to pass a Scheduler to an RxJS operator that makes it emit notifications every 5 seconds. 假设我想将调度程序传递给RxJS运算符,使其每5秒发出一次通知。 Of course, this is very easy to do by just using interval or other existing operators. 当然,仅使用interval或其他现有运算符就可以轻松完成。 But if I really want to use a scheduler to accomplish that, how would I go about it? 但是,如果我真的想使用调度程序来完成它,我该怎么做呢?

My first thought is to subclass Rx.Scheduler.default . 我的第一个想法是Rx.Scheduler.default Would that be the way to go? 这会是要走的路吗? And if so, how could that subclass look? 如果是这样,该子类怎么样? Again, I understand that this is a complicated way to accomplish something that's easy using operators, but I am just curious about custom schedulers. 同样,我理解这是一种复杂的方法来完成使用运算符很容易的东西,但我只是对自定义调度程序感到好奇。

Operations should always be independent of the Schedulers that are used to implement them. 操作应始终独立于用于实现它们的调度程序。 Schedulers only know about one thing, time. 调度员只知道一件事,时间。 Every scheduler is specifically built to deal with its own notion of time. 每个调度程序都专门用于处理自己的时间概念。 They are expressly not built to handle specific operators since that would be a conflation of concerns. 它们明确地不是为处理特定运营商构建的,因为这将是一个关注点的混合。

So for your stated goal of creating a recurring task, I wouldn't recommend trying to actually create your own scheduler, it simply isn't needed. 因此,对于您创建定期任务的既定目标,我不建议您尝试实际创建自己的调度程序,而根本不需要。 Schedulers come with an interface that already supports this. 调度程序带有一个已经支持此功能的接口。

You can use either the schedulePeriodic or the scheduleRecursiveFuture to accomplish this. 您可以使用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 1 , Reference 2 ; 参考文献1参考文献2 ;

The former should be easier to wrap your head around, essentially it is just scheduling something to occur repeatedly spaced in time based on the period parameter. 前者应该更容易包围你的头,基本上它只是根据周期参数安排在时间上重复间隔发生的事情。

The latter is usually a little more difficult to explain, but essentially you are scheduling a task and then sometime during the execution of that task you are rescheduling it (which is what the self parameter) is doing. 后者通常有点难以解释,但实际上你是在安排一个任务,然后在执行该任务的某个时候你重新安排它(这是self参数)正在做的事情。 This allows you do get the same effect using the period parameter. 这允许您使用period参数获得相同的效果。

The timing of this work is all directly affected by which scheduler you decide to pass into the operator. 这项工作的时间直接受到您决定传入运营商的调度程序的影响。 For instance, if you pass in the default it will try to use the best method for an asynchronous completion, whether that be setTimeout , setInterval or some other thing I can't remember. 例如,如果传入default ,它将尝试使用最佳方法进行异步完成,无论是setTimeoutsetInterval还是其他一些我不记得的事情。 If you pass in a TestScheduler or a HistoricalScheduler this actually won't do anything until you increment each of their respective clocks, but doing so gives fine grained control over how time flows. 如果传入TestSchedulerHistoricalScheduler ,在递增每个时钟之前实际上不会执行任何操作,但这样做可以对时间流量进行精细控制。

tl;dr Only implement new Scheduler s if you have some new overall notion of time to express, otherwise use the existing API to do work on whatever Scheduler best fits how you want time to pass. tl; dr如果你有一些新的整体时间概念,那么只实现新的Scheduler ,否则使用现有的API来做任何最适合你想要时间的Scheduler

Should you roll your own? 你应该自己动手吗?

Plainly: No. Most likely you can get done what you need done with an existing operator. 显而易见:不是。很可能你可以完成现有操作员所需的工作。 Something like buffer , window , sample , etc. Scheduler development is not completely straightforward. bufferwindowsample等。调度程序开发并不是完全简单的。


How to roll your own RxJS 4 Scheduler 如何滚动自己的RxJS 4 Scheduler

If you want to implement your own Scheduler, in RxJS 4, you'd subclass Rx.Scheduler , then override each schedule method: schedule , scheduleFuture , schedulePeriodic , scheduleRecursive , scheduleRecursiveFuture ... You'd also likely want to override now to return something relevant to your schedule. 如果你想实现自己的调度程序,在RxJS 4中,你是子类Rx.Scheduler ,然后覆盖每个调度方法: schedulescheduleFutureschedulePeriodicscheduleRecursivescheduleRecursiveFuture ......你也可能想要覆盖now返回与你的日程安排相关的东西

Here is an example of a custom scheduler that uses button clicks inside of real time 以下是使用实时内部按钮单击的自定义调度程序示例

/**
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';
  });

How to do it in RxJS 5 (alpha) 怎么做RxJS 5(alpha)

Scheduling changed again in RxJS 5 , since that version was rewritten from the ground up. RxJS 5中的调度再次发生变化,因为该版本是从头开始重写的。

In RxJS5, you can create any object that adheres to the following interface: 在RxJS5中,您可以创建任何符合以下界面的对象:

interface Scheduler {
   now(): number
   schedule(action: function, delay: number = 0, state?: any): Subscription
}

Where Subscription is just any object with an unsubscribe function (same as dispose , really) Subscription只是具有unsubscribe功能的任何对象(与dispose相同,真的)

Once again, though, I don't advise creating a scheduler unless it's completely necessary. 但是,我再次建议不要创建一个调度程序,除非它是完全必要的。

I really hope that helps answer your question. 我真的希望这有助于回答你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM