问题描述
对于任意承诺实现,延迟模式(不要与)可能看起来像:
For arbitrary promise implementation, the deferred pattern (not to be confused with antipattern) may may look like:
const deferred = new Deferred;
...
// scopes where `deferred` object reference was passed before promise settlement
deferred.promise.then((result) => { ... }, (error) => { ... });
...
deferred.resolve(...);
// doesn't affect promise state
deferred.reject();
...
// after promise settlement
deferred.promise.then((result) => { ... }, (error) => { ... });
deferred
对象持有未结算的承诺,可以是通过引用传递给其他函数作用域。所有承诺链都将在承诺结算时执行,如果 deferred.promise
在与链接之前已经结算无关紧要
或之后。承诺状态在结算后无法更改。
deferred
object holds unsettled promise that can be passed to other function scopes by reference. All promise chains will be executed on promise settlement, it doesn't matter if deferred.promise
was settled before chaining with then
or after. The state of promise cannot be changed after it was settled.
正如答案所示,最初的选择是 ReplaySubject
和 AsyncSubject
。
As the answer suggests, the initial choices are ReplaySubject
and AsyncSubject
.
对于给定的设置()
var subject = new Rx.AsyncSubject;
var deferred = subject.first();
deferred.subscribe(
console.log.bind(console, 'Early result'),
console.log.bind(console, 'Early error')
);
setTimeout(() => {
deferred.subscribe(
console.log.bind(console, 'Late result'),
console.log.bind(console, 'Late error')
);
});
这会产生理想的行为:
subject.error('one');
subject.next('two');
延迟错误1
这会导致不良行为:
subject.error('one');
subject.next('two');
subject.complete();
后期结果二
这会导致不良行为:
subject.next('two');
subject.complete();
subject.next('three');
后期结果三
ReplaySubject
的结果不同但是仍然与预期结果不一致。 next
值和错误
错误将单独处理,完成
不会阻止观察者接收新数据。这可能适用于单个 next
/ 错误
,问题是 next $ c可能会无意中多次调用$ c>或
错误
。
The results from ReplaySubject
differ but are still inconsistent with expected results. next
values and error
errors are treated separately, and complete
doesn't prevent the observers from receiving new data. This may work for single next
/error
, the problem is that next
or error
may be called multiple times unintentionally.
首先的原因()
的使用是因为 subscribe
s是一次性订阅,我想删除它们以避免泄漏。
The reason why first()
is used is because subscribe
s are one-time subscriptions, and I would like to remove them to avoid leaks.
如何用RxJS observables实现?
How should it be implemented with RxJS observables?
推荐答案
你可能正在寻找一个 Rx.ReplaySubject(1)
(或 Rx.AsyncSubject()
,具体取决于您的使用情况)。
You are probably looking for a Rx.ReplaySubject(1)
(or an Rx.AsyncSubject()
depending on your use case).
有关主题的更详细说明,请参阅。
For a more detailed explanation of subjects, see What are the semantics of different RxJS subjects?.
基本上,科目可以通过参考传递,如延期。您可以发出值(解析将是'next'
(Rxjs v5)或'onNext'
(Rxjs v4)只要您持有该引用,然后'完成'
或'onCompleted()'
)。
Basically, a subject can be passed around by reference, like a deferred. You can emit values (resolve would be an 'next'
(Rxjs v5) or 'onNext'
(Rxjs v4) followed by 'complete'
or 'onCompleted()'
) to it, as long as you hold that reference.
您可以拥有任何数量的主题订阅者,类似于然后
到延迟。如果您使用 replaySubject(1)
,任何订阅者都将收到最后一个发布的值,该值应该回答您的如果deferred.promise无关紧要在与之后或之后的链接之前已经解决。
。在Rxjs v4中, replaySubject
将在订阅完成后向订阅者发出最后一个值。我不确定Rxjs v5中的行为。
You can have any amount of subscribers to a subject, similar to the then
to a deferred. If you use a replaySubject(1)
, any subscribers will receive the last emitted value, which should answer your it doesn't matter if deferred.promise was settled before chaining with then or after.
. In Rxjs v4, a replaySubject
will emit its last value to a subscriber subscribing after it has completed. I am not sure about the behaviour in Rxjs v5.
- https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/asyncsubject.md
- https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/replaysubject.md
:
var subject = new Rx.AsyncSubject();
var deferred = subject;
deferred.subscribe(
console.log.bind(console, 'First result'),
console.log.bind(console, 'First error')
);
setTimeout(() => {
deferred.subscribe(
console.log.bind(console, 'Second result'),
console.log.bind(console, 'Second error')
);
});
subject.onNext('one');
subject.onCompleted();
subject.onNext('two');
subject.onNext('three');
subject.onNext('four');
产生以下输出:
First result one
Second result one
然而,使用Rxjs v5执行的相同代码:
However, the same code executed with Rxjs v5 does not :
First result one
Second result four
所以基本上这意味着科目的语义在Rxjs v5中发生了变化 !!!这真的是一个需要注意的突破性变化。无论如何,你可以考虑回到Rxjs v4,或者在他的回答中使用artur grzesiak建议的转变。您还可以在github网站上提交问题。我认为这种改变是故意的,但是在它出现的时候并非如此,提交这个问题可能有助于澄清这种情况。在任何情况下,无论选择何种行为都应该正确记录。
So basically that means that subjects' semantics have changed in Rxjs v5!!! That really is a breaking change to be aware of. Anyways, you could consider moving back to Rxjs v4, or use the turnaround suggested by artur grzesiak in his answer. You could also file an issue on the github site. I would believe that the change is intentional, but in the advent it is not, filing the issue might help clarify the situation. In any case, whatever behaviour chosen should definitely be documented properly.
以链接显示与
这篇关于使用RxJS 5可观察量的延迟模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!