RxJS:Auto(dis)connect on(un)订阅Websockets和Stomp
我正在为Stomp over WebSocket构建一个小小的RxJS包装器,它已经可以工作了 但是现在我想到了一个非常酷的特性,它可能(如果我错了,希望能纠正我的错误)很容易用RxJS实现 当前行为: 如您所见,我必须等待RxJS:Auto(dis)connect on(un)订阅Websockets和Stomp,rxjs,reactive-programming,rxjs5,reactivex,reactive,Rxjs,Reactive Programming,Rxjs5,Reactivex,Reactive,我正在为Stomp over WebSocket构建一个小小的RxJS包装器,它已经可以工作了 但是现在我想到了一个非常酷的特性,它可能(如果我错了,希望能纠正我的错误)很容易用RxJS实现 当前行为: 如您所见,我必须等待state==“CONNECTED”才能订阅subscribedestation(…)。否则我会从Stomp库中得到一个错误 新行为: 下一个实现应该会让用户更容易。以下是我的想象: myStompWrapper.configure("/stomp_endpoint");
state==“CONNECTED”
才能订阅subscribedestation(…)
。否则我会从Stomp库中得到一个错误
新行为:
下一个实现应该会让用户更容易。以下是我的想象:
myStompWrapper.configure("/stomp_endpoint");
var subscription = myStompWrapper.subscribeDestination("/foo")
.subscribe(msg => console.log(msg));
// ... and some time later:
subscription.unsubscribe();
它应该如何在内部工作:
myStompWrapper.configure("/stomp_endpoint");
myStompWrapper.connect();
myStompWrapper.observeDestination("/foo")
.subscribe(..);
myStompWrapper.observeDestination("/bar")
.subscribe(..);
myStompWrapper.configure("/stomp_endpoint");
let subscription1 = myStompWrapper.observeDestination("/foo")
.subscribe(..); // execute connect(), because this
// is the first subscription
let subscription2 = myStompWrapper.observeDestination("/bar")
.subscribe(..);
subscription2.unsubscribe();
subscription1.unsubscribe(); // execute disconnect(), because this
// was the last subscription
configure
只能在断开连接时调用
subscribedestation
时,有两种可能性:
已连接
:只需订阅目的地即可断开连接
:首先调用connect()
,然后订阅目标unsubscribe
时,有两种可能:
disconnect()
错误。但这没什么大不了的
stompClient.connect(..)是非阻塞的。它有一个onSuccess
回调:
public connect() {
stompClient.connect({}, this.onSuccess, this.errorHandler);
}
public onSuccess = () => {
this.state.next(State.CONNECTED);
}
observeDestination(..)订阅Stomp消息频道(=目的地),并返回一个Rx.observeable
,然后可用于取消订阅此Stomp消息频道:
public observeDestination(destination: string) {
return this.state
.filter(state => state == State.CONNECTED)
.flatMap(_ => Rx.Observable.create(observer => {
let stompSubscription = this.client.subscribe(
destination,
message => observer.next(message),
{}
);
return () => {
stompSubscription.unsubscribe();
}
}));
}
可以这样使用:
myStompWrapper.configure("/stomp_endpoint");
myStompWrapper.connect();
myStompWrapper.observeDestination("/foo")
.subscribe(..);
myStompWrapper.observeDestination("/bar")
.subscribe(..);
myStompWrapper.configure("/stomp_endpoint");
let subscription1 = myStompWrapper.observeDestination("/foo")
.subscribe(..); // execute connect(), because this
// is the first subscription
let subscription2 = myStompWrapper.observeDestination("/bar")
.subscribe(..);
subscription2.unsubscribe();
subscription1.unsubscribe(); // execute disconnect(), because this
// was the last subscription
现在我想摆脱myTompRapper.connect()
。当第一个用户通过调用observeDestination(..).subscribe(..)
进行订阅时,代码应自动调用this.connect()
,当最后一个用户调用unsubscribe()
时,代码应调用this.disconnect()
示例:
myStompWrapper.configure("/stomp_endpoint");
myStompWrapper.connect();
myStompWrapper.observeDestination("/foo")
.subscribe(..);
myStompWrapper.observeDestination("/bar")
.subscribe(..);
myStompWrapper.configure("/stomp_endpoint");
let subscription1 = myStompWrapper.observeDestination("/foo")
.subscribe(..); // execute connect(), because this
// is the first subscription
let subscription2 = myStompWrapper.observeDestination("/bar")
.subscribe(..);
subscription2.unsubscribe();
subscription1.unsubscribe(); // execute disconnect(), because this
// was the last subscription
我同意你建议把代码塞进MyTompRapper的新家里会更快乐
我仍然建议使用像observeDestination
这样的名称,而不是subscribedestinition(“/foo”)
,因为您实际上并不是从该方法订阅,而是完成您的可观察链
configure()
只能在断开连接时调用
如果在未断开连接的情况下调用它,您不需要在此处指定应该发生什么。由于您在这里似乎没有返回任何要使用的值,因此我假设您打算在异常状态不方便时抛出异常。为了跟踪这些状态,我将使用一个behavior subject
,它以DISCONNECTED
的初始值开始。您可能希望将状态保持在observeDestination
中,以决定是否抛出异常
如果已连接:只需订阅目标
如果断开连接:首先调用connect(),然后订阅目标
正如我前面提到的,如果订阅不是发生在subscribedestinition(“/foo”)
中,而是你只是构建了你的可观察链,我想你会更快乐。在某些情况下,您只需要调用connect()
,我只需要在包含状态条件的可观察链中使用.do()
调用
要使用rx-y逻辑,您可能需要调用disconnect()
,作为observable unsubscribe的一部分,并简单地返回一个共享的refcounted observable。这样,每个新订户就不会重新创建新的订阅,而是。refCount()
将对可观察链进行单个订阅,并且取消订阅()
一旦下游不再有订户
假设消息以的形式传入,则mytompwrapper
中的observedData$作为mytompwrapper
的一部分,我的建议代码将如下所示:
observeDestination() {
return Rx.Observable.create(function (observer) {
var subscription = this.getState()
.filter(state => state == "CONNECTED")
.do(state => state ? this.connect() : Observable.of(true))
.switchMap(this.observedData$)
.refCount();
.subscribe(value => {
try {
subscriber.next(someCallback(value));
} catch(err) {
subscriber.error(err);
}
},
err => subscriber.error(err),
() => subscriber.complete());
return { unsubscribe() { this.disconnect(); subscription.unsubscribe(); } };
}
因为我丢失了您的一些代码,所以我允许自己不测试代码。但希望它能说明并呈现我在回答中提到的概念。
我同意你建议把代码塞进MyTompRapper的新家里会更快乐
我仍然建议使用像observeDestination
这样的名称,而不是subscribedestinition(“/foo”)
,因为您实际上并不是从该方法订阅,而是完成您的可观察链
configure()
只能在断开连接时调用
如果在未断开连接的情况下调用它,您不需要在此处指定应该发生什么。由于您在这里似乎没有返回任何要使用的值,因此我假设您打算在异常状态不方便时抛出异常。为了跟踪这些状态,我将使用一个behavior subject
,它以DISCONNECTED
的初始值开始。您可能希望将状态保持在observeDestination
中,以决定是否抛出异常
如果已连接:只需订阅目标
如果断开连接:首先调用connect(),然后订阅目标
正如我前面提到的,如果订阅不是发生在subscribedestinition(“/foo”)
中,而是你只是构建了你的可观察链,我想你会更快乐。在某些情况下,您只需要调用connect()
,我只需要使用.do()