调度器控制某个订阅何时开始以及何时传递通知。
- 调度器是一种数据结构。它知道如何根据优先级或其它标准来存储和对任务进行排队。
- 调度器是一个执行上下文。它表示任务在何时何地执行(例如立即执行,或在另一个回调机制中,如 setTimeout 或 process.nextTick,或动画帧)。
- 调度器有一个(虚拟)时钟。它通过调度器上的 getter 方法 now() 提供了“时间”的概念。在特定调度器上调度的任务将仅遵守该时钟指示的时间。
调度器允许你定义 Observable 将在什么执行上下文中向其 Observer 传递通知。
使用操作符 observeOn 指定用于传递这些值的 async 调度器:
import { Observable, observeOn, asyncScheduler } from 'rxjs';
const observable = new Observable((observer) => {
observer.next(1); //proxyObserver.next(1);
observer.next(2); //..
observer.next(3); //..
observer.complete(); //proxyObserver.complete();
}).pipe(
observeOn(asyncScheduler)
);
console.log('just before subscribe');
observable.subscribe({ //observable.subscribe(finalObserver);
next(x) {
console.log('got value ' + x);
},
error(err) {
console.error('something wrong occurred: ' + err);
},
complete() {
console.log('done');
},
});
console.log('just after subscribe');
//just before subscribe
//just after subscribe
//got value 1
//got value 2
//got value 3
//done
这是因为 observeOn(asyncScheduler) 在 new Observable 和最终的 Observer 之间引入了一个代理 Observer。
async 调度器使用 setTimeout 或 setInterval 运行
Scheduler 的 schedule() 方法会接受一个 delay 参数,它指的是相对于 Scheduler 内部时钟的时间量。
这在测试中特别有用,其中可以使用虚拟时间调度器来伪造挂钟时间,而实际上是同步执行计划任务。
调度器类型
async 调度器是 RxJS 提供的内置调度器之一。
每一个调度器都可以通过使用 Scheduler 对象的静态属性来创建和返回。
使用调度器
如果你不提供调度器,RxJS 会根据最少并发的原则选择一个默认的调度器
例如,
对于返回具有有限且少量消息的 observable 的操作符,RxJS 不使用调度器,即 null 或 undefined。
对于返回可能大量或无限数量的消息的操作符,会使用 queue 调度器。
对于使用计时器的操作符,会使用 async 调度器。
静态创建操作符通常以某个 Scheduler 作为参数。
例如,from(array, scheduler) 允许你指定在传递从 array 转换出来的每个通知时要使用的调度器。
它通常是操作符的最后一个参数。
1. 使用 subscribeOn 来安排 subscribe() 在什么上下文中发生调用。
默认情况下,对 Observable 的 subscribe() 调用将同步并立即发生。
但是,可以使用实例操作符 subscribeOn(scheduler) 来推迟或安排在给定调度器上发生的实际订阅其中 scheduler 是你要提供的参数。
2. 使用 observeOn 来安排在什么上下文中发送通知。
正如我们在上面的例子中看到的,实例操作符 observeOn(scheduler) 在源 Observable 和目标 Observer 之间引入了一个中介 Observer,此中介会使用给定的 scheduler 调度对目标 Observer 的调用。
3. 实例操作符可以将调度器作为参数。
与时间相关的操作符,如 bufferTime、debounceTime、delay、auditTime、sampleTime、throttleTime、timeInterval、timeout、timeoutWith、windowTime 都将 Scheduler 作为最后一个参数,否则默认在 asyncScheduler 上运行。
请注意,cache 和 publishReplay 都接受 Scheduler,因为它们使用了 ReplaySubject。
ReplaySubjects 的构造函数将可选的 Scheduler 作为最后一个参数,因为 ReplaySubject 可能会处理时间,这仅在 Scheduler 的上下文中才有意义。
默认情况下,ReplaySubject 会使用 queue 调度器提供时钟