我希望答案是forkJoin
/ Promises.all
,但还有一点,请耐心等待。
我有一个承诺的来源,可以按随机顺序到达,我需要一些方式来说"当到目前为止到达的所有承诺都已完成时,让我知道"。
在基于Promise的解决方案中,我认为最初使用的是Promise.all
,但承诺仍然可以#34;到达"而其他人还没有完成。有趣的是,对于一个可迭代的Promise.all"有一个很好的解决方法。在https://stackoverflow.com/a/37819138/239168
我试图以Rx的方式做这件事。在阅读了一些文档之后,我认为forkJoin
是等效的Promise.all
,但同样的问题,没有时间我可以安全地调用forkJoin
或{{1}因为总会有另外一个被添加而另一个仍在等待...因为我现在可能没有意义,我想我会要求一些指导。
设置
(如果它很傻,请抓住你的笑声,我是Rx的新手......)
我有一个主题,我想知道它的所有承诺何时完成...它也可以随时获得新的承诺......
Promise.all
每当新承诺到达时,我只是将其添加到主题
private promiseSource = new Subject<Promise<any>>();
promises$ = this.promiseSource.asObservable();
我想要神奇地发生的事情是 - 让主题&#34;完成&#34;只要它只保留完成的承诺。
e.g。
this.promiseSource.next(somePromise);
或者换句话说,我有一个可观察到的异步操作,如果我们看一下内容,我们可以看到重叠的异步操作,我想知道什么时候没有重叠,例如
promises$.magicFlatMapForkJoinConcatMapTrickery().subscribe({
next: x => ...,
error: err => ...,
complete: () => {
console.log('all promises we got so far are done');
// nice to have, I want this to keep "listening" for new promises
promiseSource.youAreNotREALYCompletePleaseReset();
}
});
如果这些是例如http电话,我基本上要求 - 告诉我什么时候没有打开http电话。
tl; dr
如何在RxJS世界中实现这个基于Promises的答案......
答案 0 :(得分:2)
如果我正确地解释了您的问题,您只对指示是否有未决承诺的信号感兴趣。
使用merge
和scan
来创建一个可以发出待处理承诺计数的观察点非常容易,从中你应该能够创建自己喜欢的任何信号。
基本上,每当主体发出承诺时,应该递增未决承诺的数量。每当其中一个承诺结算时,计数就会减少。
const promises = new Rx.Subject();
const pendingCount = Rx.Observable
.merge(
promises.mapTo(1),
promises.mergeMap(p => Rx.Observable.from(p).mapTo(-1))
)
.scan((acc, value) => acc + value, 0)
.do(count => console.log(`${count} pending promise(s)`));
const doneSignal = pendingCount
.filter(count => count === 0)
.mapTo("done");
doneSignal.subscribe(signal => console.log(signal));
const timeoutPromise = (delay) => new Promise(resolve => setTimeout(resolve, delay));
promises.next(timeoutPromise(200));
setTimeout(() => promises.next(timeoutPromise(200)), 100);
setTimeout(() => promises.next(timeoutPromise(200)), 300);
setTimeout(() => promises.next(timeoutPromise(200)), 700);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
答案 1 :(得分:1)
我可以根据之前的答案想出一个相当简单的方法。您可以使用fromPromise
将Subject<Promise<any>>
转换为Subject<Observable<any>>
,然后您可以使用this答案中描述的active
功能将其降低为观察到有效的可观测量。一旦你有了这个,你就可以将你的查询短语称为&#34;当活动流数组变空时#34;这可以用一个简单的过滤器来完成,例如:
active(yourSubjectOfObservables).filter(x => x.length === 0).subscribe(() => {
// here we are, all complete
});
每当活动流的数量转换为零时,这将触发,因此如果您只想第一次,请在过滤器和订阅之间放置.take(1)
或。first
。
可能不是最漂亮的解决方案,但它在概念上很简单。