rxjs: QueueScheduler schedule method: this.SchedulerAction is not a constructor
RxJS version: 5.0.0-beta11
Actual behavior: I tried to use the beta 11 today in the project I’m working on, and the QueueSchduler schedule method raises the following error: TypeError: this.SchedulerAction is not a constructor.
Code to reproduce: Actually it seems that the SchedulerAction is not defined. The error is raised by running the schedule method of an instance we create:
scheduler = new QueueScheduler();
scheduler.schedule(() => someSubject.next(someState), 0)
Additional information: By reading the Scheduler class, I found out the constructor does not set the SchedulerAction attributes:
constructor(private SchedulerAction: typeof Action,
now: () => number = Scheduler.now) {
this.now = now;
}
I may missed something, but is the following line not missing ?
this.SchedulerAction = SchedulerAction;
Also, the QueueScheduler class could reuse the Scheduler constructor with QueueAction by default ?
// QueueScheduler.ts
export class QueueScheduler extends AsyncScheduler {
constructor(private SchedulerAction: typeof Action = QueueAction) {
super(SchedulerAction);
}
}
// queue.ts
export const queue = new QueueScheduler();
Im also wondering if I’m doing wrong when instantiating a QueueScheduler, maybe only use Scheduler.queue could be sufficient…
Thanks for this great repo !
++
Augustin
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 15 (8 by maintainers)
@trxcllnt yeah, I think we should pair program on the
VirtualTimeScheduler
stuff because I think there is a lot of value to it to have a more complete swappable clock. I think you captured the essence in that we need the basics.The scheduler itself should be initialized with an initial clock value, as well as a comparer for values to determine whether we need to increment the clock. We made the virtual time scheduler overly generic and I’m not sure it’s super necessary to have all the ceremony we had before.
The following methods should be supported:
sleep
- Advance the clock without running any of the scheduled workadvanceTo
- Advance the clock to an absolute time and run all scheduled workadvanceBy
- Advance the clock by a relative time and run all scheduled workschedule
-Obviously to schedule the workstart
- Starts the schedulerstop
- Stops the schedulerWhy don’t we get started on this, so we could add some nicer stuff for historical scheduling as well?
@mattpodwysocki yes! happy to be moving forward on this. just pushed a
virtual-time-schedulers
branch for us to collaborate.IIRC the thing we’ve been calling the VirtualTimeScheduler was hastily implemented to support writing tests as marble diagrams, but nobody’s had the time (heh) to carry it to the finish line.
I was hoping at some point @mattpodwysocki would want to collaborate on the remaining Scheduler features 😃. Though seeing as how I’ve mostly failed to communicate the requirements and designs of the new Schedulers in detail, I’ll take the blame for dropping the ball here. So in the interest of at least getting this info down somewhere, the rest of this post will be all the what and why details I can remember about the new Schedulers. @jayphelps hopefully this will also help you if you’re on Scheduler maintenance duty.
A Scheduler is a sorted queue of things to do. Just like all the other versions of Rx, it schedules each thing to do as a disposable Action, so an Action extends Subscription (aka Disposable). The Scheduler constructors accept an Action class. When you call
schedule()
, the Scheduler creates and returns you an instance of this class.To schedule something to happen in the future, we started with the simplest API we could (but no simpler), initially only supporting relative due times:
We identified disposable and closure allocation, closure invocation, and async request call patterns as the major performance bottlenecks, but we wanted to keep the familiar recursive scheduling API and reentrancy behaviors. Thus, the Schedulers were factored into two separate components, for performance and extensibility:
The Action instance is responsible for updating the shared queue of the Scheduler it was created by. An Action is responsible for insertion, removal, ordering, and flushing its Scheduler’s queue. This may initially seem counter-intuitive; we wouldn’t typically allow a queue to be updated by the things that go in it. However, this approach allowed us to make a number of key performance improvements while keeping the core, familiar recursive scheduling API:
Observable.interval(0)
, no matter how many periods elapse. This can dramatically reduce memory pressure/GC cost in scenarios with many concurrent periodically scheduled Actions. VirtualActions (created by the VTScheduler) are immutable, because they need to be inspected by the TestScheduler to ensure each execution of work does what it’s supposed to.0
due time, and it will be run by its original Scheduler.setInterval
instead of serialsetTimeout
calls. This is less stressful on the VM for Actions with stable periods, but also ensures singly-executed Actions are consistently invoked in order with respect to other Actions (both periodic or otherwise). The VM invokessetInterval
callbacks as close to the time they should execute, adjusting for time lost in long frames under load, providing a more accurate picture of “real” time.When it’s time to flush a Scheduler’s queue, the Scheduler executes each Action, handling errors and reentrancy. For example, the Async and Queue Schedulers guard against recursion by pushing rescheduled actions to the end of the queue and unwinding the stack. This is identical to previous versions of Rx. By default, the production Schedulers stop executing if an Action returns an Error, and disposes the rest of the scheduled Actions. There’s probably room to experiment here.
Early on we made a decision to switch the default scheduling semantics from trampolining (aka CurrentThreadScheduler) to recursive (aka RecursiveScheduler). However instead of implementing a new RecursiveScheduler, RxJava proved that defaulting to iterative loops in the absence of a Scheduler yields identical call patterns, and is dramatically faster in most cases.
So to finish the VTScheduler, we need to add a public API for start, stop, sleep, sorting and comparing time, scheduling by absolute time, and advancing by relative and absolute time (instead of count). @mattpodwysocki did I miss anything?