RxJS5 WebSocketSubject - 如何过滤和完成消息?

时间:2016-10-08 16:26:18

标签: websocket rxjs rxjs5

我正在寻找关于使用RxJS 5设置WebSocket连接的正确方法的一些指导。我正在连接到使用JSON-RPC 2.0的WebSocket。我希望能够执行一个向WS发送请求的函数,并从服务器返回相关响应的Observable。

我设置了我的初始WebSocketSubject,如下所示:

const ws = Rx.Observable.webSocket("<URL>")

从这个观察中,我已经能够使用ws.next(myRequest)发送请求,并且我已经能够看到通过ws`观察到的响应。

我一直在努力创建能够过滤ws对正确响应的响应然后完成的函数。这些似乎完成了源主题,停止了所有未来的ws请求。

我的预期输出类似于:

function makeRequest(msg) {
    // 1. send the message
    // 2. return an Observable of the response from the message, and complete
}

我尝试了以下内容:

function makeRequest(msg) {
    const id = msg.id;
    ws.next(msg);
    return ws
        .filter(f => f.id === id)
        .take(1);
}

但是,当我这样做时,只有第一个请求才有效。后续请求无法正常工作,我相信因为我正在完成take(1)

对这种情况的适当架构有何想法?

1 个答案:

答案 0 :(得分:1)

如果没有其他订阅者,似乎有错误或故意设计决定关闭取消订阅WebSocket。如果您对此感兴趣,请查看相关的source

基本上,您需要保证始终有订阅者,否则WebSocket将被关闭。你可以用两种方式做到这一点。

路线A是更具语义性的方式,基本上您创建了Observable Subject部分的已发布版本,您可以对其进行更精细的控制。

const ws = Rx.Observable.webSocket("<URL>");
const ws$ = ws.publish();

//When ready to start receiving messages
const totem = ws$.connect();

function makeRequest(msg) {
    const { id } = msg;
    ws.next(msg);
    return ws$.first(f => f.id === id)
}

//When finished
totem.unsubscribe();

路由B是创建一个只保存套接字的令牌订阅,但是根据应用程序的实际生命周期,您可以很好地附加到某种关闭事件,以确保它始终关闭。即。

const ws = Rx.Observable.webSocket("<URL>");

const totem = ws.subscribe();

//Later when closing:
totem.unsubscribe();

正如您所看到的,两种方法都非常相似,因为它们都创建了订阅。 B的主要缺点是你创建了一个空的订阅,它将被抽取所有的事件只是为了扔掉它们。他们只有B的优势在于您可以使用相同的变量引用Subject进行排放和订阅,而您必须注意使用ws$进行订阅。

如果您真的如此倾向,可以使用Subject创建功能来优化路线A:

const safeWS = Rx.Subject.create(ws, ws$);

以上内容允许您使用相同的变量,但是当您完成后,您仍然有责任关闭ws$并传递WebSocket