让我们说我想将调度程序传递给RxJS运算符,使其每5秒发出一次通知。当然,只需使用interval
或其他现有运算符即可轻松完成。但如果我真的想用一个调度程序来完成它,我该怎么做呢?
我的第一个想法是继承Rx.Scheduler.default
。这会是要走的路吗?如果是这样,该子类怎么样?同样,我理解这是一种复杂的方法来完成使用操作符的简单方法,但我只是对自定义调度程序感到好奇。
答案 0 :(得分:4)
操作应始终独立于用于实现它们的调度程序。调度员只知道一件事,时间。每个调度程序都专门用于处理自己的时间概念。它们明确地不构建来处理特定的运营商,因为这将是一个关注的混合。
因此,对于您创建定期任务的既定目标,我不建议您尝试实际创建自己的调度程序,但根本不需要。调度程序带有一个已经支持此功能的接口。
您可以使用schedulePeriodic
或scheduleRecursiveFuture
来完成此操作。
//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);
});
});
};
前者应该更容易包围,基本上只是根据周期参数安排在时间上重复间隔发生的事情。
后者通常有点难以解释,但实质上你是在安排一项任务,然后在执行该任务的某个时候,你重新安排它(这就是{{1} }参数)正在做。这允许您使用period参数获得相同的效果。
这项工作的时间直接受到您决定传入运营商的调度程序的影响。例如,如果您传入self
,它将尝试使用最佳方法进行异步完成,无论是default
,setTimeout
还是其他一些我不记得的事情。如果你传入一个setInterval
或TestScheduler
,那么在递增每个时钟之前实际上不会做任何事情,但这样做可以很好地控制时间流量。
tl; dr 如果你有一些新的总体时间概念表达,那么只能实现新的HistoricalScheduler
,否则使用现有的API来处理Scheduler
最好的Scheduler
符合你想要时间的方式。
答案 1 :(得分:1)
明白:不会。很可能你可以完成现有操作员所需的工作。像buffer
,window
,sample
等等。调度程序开发并不是完全简单。
如果您想要在RxJS 4中实现自己的调度程序,那么您将继承Rx.Scheduler
,然后覆盖每个调度方法:schedule
,scheduleFuture
,{{1} },schedulePeriodic
,scheduleRecursive
...您也可能希望覆盖scheduleRecursiveFuture
以返回与您的日程安排相关的内容。
Here is an example of a custom scheduler that uses button clicks inside of real time
now
计划在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
相同,真的)
但是,除非完全有必要,否则我不建议创建一个调度程序。
我真的希望这有助于回答你的问题。