在使用具有延迟传递的Observable的代码中,我可以使用TestScheduler在虚拟时间内使传递无实际延迟。但是,似乎如果我将这样的Observable转换为Promise并尝试将它们链接在一起,那么只有第一个Promise才能得到解决。如何在不等待实时解决的情况下测试使用此类延迟的系统?
请参阅下面的剪辑:请注意更改' sched'到'异步'并评论出' flush'除了缓慢之外,line会使它按预期运行。如何在没有延迟的情况下运行这一系列承诺?
var sched = new Rx.TestScheduler();
//var sched = Rx.Scheduler.async;
Rx.Observable.timer (100, sched).toPromise ().then (
() => $("#test").text("100")).then (
() => Rx.Observable.timer (100, sched).toPromise ()).then (
() => $("#test").text("200")).then (
() => Rx.Observable.timer (100, sched).toPromise ()).then (
() => $("#test").text("300")).then (
() => Rx.Observable.timer (100, sched).toPromise ()).then (
() => $("#test").text("400"));
sched.flush ();

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.4.0/dist/global/Rx.min.js"></script>
<div id="test"></div>
&#13;
答案 0 :(得分:0)
问题是在解析Promise之后,直到控制流返回到顶层之后才会调用其回调。这意味着在调用sched.flush()
期间解决第一个承诺后,新的回调会排队,但直到sched.flush()
完成后才会发生这种情况。但是我们仍然需要sched.flush()
再次运行以使第二个Observable完成,依此类推。
原则上,这意味着我们只需要异步重新调用sched.flush()
几次,以便完成所有可观察对象。我们可以通过创建一个单独的Promise链来执行此操作,该链在每个回调上刷新调度程序。唯一的问题是,目前还不清楚如何判断Observable是否已经准备就绪,因为没有明确定义的无关Promise回调的执行顺序。
我的解决方案只是创建一个Promise链,它执行一个刷新调度程序的回调函数,然后递归重新插入,直到它发现它不再需要这样做。这依赖于原始的回调产生某种可以测试的副作用(但是由于要求单元测试,这似乎是合理的 - 如果没有这样的效果,它就不可测试在第一种情况下)。在实际代码中,它还需要在检测到代码结束后执行任何断言,测试拆解等。我还安排它以便它具有有限的迭代次数,因此如果测试的代码以某种方式失败,它不会无限地递归。
var sched = new Rx.TestScheduler();
var finished = false;
//var sched = Rx.Scheduler.async;
Rx.Observable.timer (100, sched).toPromise ().then (
() => $("#test").text("100")).then (
() => Rx.Observable.timer (100, sched).toPromise ()).then (
() => $("#test").text("200")).then (
() => Rx.Observable.timer (100, sched).toPromise ()).then (
() => $("#test").text("300")).then (
() => Rx.Observable.timer (100, sched).toPromise ()).then (
() => $("#test").text("400")).then (
() => finished = true );
let f = n => {
sched.flush ();
if (n > 0 && !finished) {
return Promise.resolve(n - 1).then(f);
}
else {
$("#test").append (" [" + n + " iterations left]");
}
}
Promise.resolve(100).then(f);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.4.0/dist/global/Rx.min.js"></script>
<div id="test"></div>
&#13;