我正在构建一个用于Stomp over Websockets的小型RxJS Wrapper,它已经可以使用了。
但现在我想到了一个非常酷的功能,可能(希望 - 如果我错了,请纠正我)使用RxJS轻松完成。
myStompWrapper.configure("/stomp_endpoint");
myStompWrapper.connect(); // onSuccess: set state to CONNECTED
// state (Observable) can be DISCONNECTED or CONNECTED
var subscription = myStompWrapper.getState()
.filter(state => state == "CONNECTED")
.flatMap(myStompWrapper.subscribeDestination("/foo"))
.subscribe(msg => console.log(msg));
// ... and some time later:
subscription.unsubscribe(); // calls 'unsubscribe' for this stomp destination
myStompWrapper.disconnect(); // disconnects the stomp websocket connection
如您所见,必须等待state == "CONNECTED"
才能订阅subscribeDestination(..)
。否则我会从Stomp库中得到错误。
下一个实现应该让用户更容易。这就是我的想象:
myStompWrapper.configure("/stomp_endpoint");
var subscription = myStompWrapper.subscribeDestination("/foo")
.subscribe(msg => console.log(msg));
// ... and some time later:
subscription.unsubscribe();
内部如何运作
configure
只能在DISCONNECTED
subscribeDestination
时,有两种可能性:
CONNECTED
:只是订阅目的地DISCONNECTED
:先致电connect()
,然后订阅目的地unsubscribe
时,有两种可能性:
disconnect()
我还不确定如何到达那里,但这就是我在这里提出这个问题的原因;-)
提前致谢!
在不断开连接时调用 configure()时,它应该抛出Error
。但这不是什么大问题。
stompClient.connect(..)是非阻止的。它有一个onSuccess
回调:
public connect() {
stompClient.connect({}, this.onSuccess, this.errorHandler);
}
public onSuccess = () => {
this.state.next(State.CONNECTED);
}
observeDestination(..)订阅Stomp消息频道(=目的地)并返回Rx.Observable
,然后可以用来取消订阅此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.connect()
。代码应在第一个订阅时通过调用this.connect()
自动调用observeDestination(..).subscribe(..)
,并在最后一个调用this.disconnect()
时调用unsubscribe()
。
示例:
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
答案 0 :(得分:0)
RxJS: Auto (dis)connect on (un)subscribe with Websockets and Stomp
我同意你建议收藏到myStompWrapper的代码在新家里会更快乐。
我仍然建议使用observeDestination
而不是subscribeDestination("/foo")
之类的名称,因为您实际上并未订阅该方法,而只是完成您的可观察链。
configure()
只能在DISCONNECTED
如果在DISCONNECTED
之间调用它时,您没有指定应该发生什么。由于您似乎没有返回任何您将使用的值,我将假设您打算在状态不方便时抛出异常。要跟踪此类状态,我会使用以BehaviourSubject
的初始值开头的DISCONNECTED
。您可能希望在observeDestination
内保持状态以决定是否抛出异常
如果已连接:只需订阅目的地
如果DISCONNECTED:首先调用connect(),然后订阅目标
正如我之前提到的,如果订阅不在subscribeDestination("/foo")
内发生,我认为你会更高兴,而只是建立你的可观察链。由于您只是想在某些情况下调用connect()
,我只需在您的可观察链中使用.do()
调用,该调用包含状态条件。
要使用rx-y逻辑,您可能希望将disconnect()
作为可观察的取消订阅的一部分,并简单地返回一个共享的refcounted observable来开始。这样,每个新订阅者都不会重新创建新订阅,而.refCount()
只会在下游没有订阅者的情况下对可观察链和unsubscribe()
进行单一订阅。
假设消息是以myStompWrapper
中的 this.observedData $ 进入的,myStompWrapper
中我建议的代码看起来像这样:
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(); } };
}
因为我遗漏了一些代码,所以我不允许自己测试代码。但希望它能说明并提出我在答案中提到的概念。