不通过调度程序的 RxJS 测试 Observable 序列

RxJS Testing Observable sequence without passing scheduler

我在尝试测试类似于以下函数的一段代码时遇到问题。

问题基本上可以归结为:是否可以更改 debounce 运算符的调度程序而不将单独的 Scheduler 传递给函数调用?

下面的例子应该更具体地解释用例。我正在尝试测试类似于以下的一段代码。我想测试函数中的链(使用 TestScheduler),而不必将调度程序传递给 debounce() 运算符。

// Production code
function asyncFunctionToTest(subject) {
  subject
    .tap((v) => console.log(`Tapping: ${v}`))
    .debounce(1000)
    .subscribe((v) => {
      // Here it would call ReactComponent.setState()
      console.log(`onNext: ${v}`)
    });
}

测试文件将包含以下代码来调用函数并确保主题发出值。

// Testfile
const testScheduler = new Rx.TestScheduler();
const subject = new Rx.Subject();

asyncFunctionToTest(subject);

testScheduler.schedule(200, () => subject.onNext('First'));
testScheduler.schedule(400, () => subject.onNext('Second'))
testScheduler.advanceTo(1000);

上面的测试代码仍然需要一秒钟的时间来进行去抖动。我找到的唯一解决方案是将 TestScheduler 传递给函数并将其传递给 debounce(1000, testScheduler) 方法。这将使去抖运算符使用测试调度程序。

我最初的想法是使用observeOnsubscribeOn通过更改

来更改整个操作链中使用的defaultScheduler
asyncFunctionToTest(subject);

类似于 asyncFunctionToTest(subject.observeOn(testScheduler));asyncFunctionToTest(subject.subscribeOn(testScheduler));

这并没有给我预期的结果,但是我想我可能不完全理解 observeOnsubscribeOn 运算符的工作方式。 (我现在估计,当使用这些操作符时,它会改变整个操作链的调度程序运行,但操作符仍然选择他们自己的调度程序,除非特别通过?)

以下 JSBin 包含我在调度程序中传递的 运行nable 示例。 http://jsbin.com/kiciwiyowe/1/edit?js,console

不,不是真的,除非你真的修补了 RxJS 库。我知道这是最近作为 issue 提出的,并且可能支持说,能够在将来的某个时候更改 DefaultScheduler 的内容,但目前无法可靠地完成。

有什么理由不能包含调度程序吗?所有接受 Schedulers 的操作员都已经选择这样做并具有合理的默认值,所以它真的不需要任何成本,因为您的生产代码可以简单地忽略该参数。

为什么简单地添加 observeOnsubscribeOn 并不能解决问题,更一般地说,这两个运算符实际上只影响事件在 after[ 之后的传播方式=27=]他们已经被那个接线员收到了。

例如,您可以通过执行以下操作来实现 observeOn

Rx.Observable.prototype.observeOn = (scheduler) => {
  var source = this;
  return Rx.Observable.create((observer) => {
    source.subscribe(x => 
       {
         //Reschedule this for a later propagation
         scheduler.schedule(x, 
             (s, state) => observer.onNext(state)); 
       },
       //Errors get forwarded immediately
       e => observer.onError(e),
       //Delay completion 
       () => scheduler.schedule(null, () => observer.onCompleted()))
  });

};

以上所做的只是重新安排传入的事件,如果下游或上游的操作员有其他延迟,则此操作员对其没有影响。 subscribeOn 具有类似的行为,只是它重新安排订阅而不是事件。