RxJS:将Node.js套接字转换为Observable并将它们合并为一个流

时间:2015-09-27 16:01:38

标签: node.js rxjs

我正在尝试使用RxJS将Node的套接字转换为流。目标是让每个套接字创建自己的流并将所有流合并为一个。当新的套接字连接时,会使用socketStream = Rx.Observable.fromEvent(socket, 'message')创建一个流。

然后将流合并到主流中,类似于

mainStream = mainStream.merge(socketStream)

这似乎工作正常,问题是在200-250客户端连接后,服务器抛出RangeError: Maximum call stack size exceeded

我有一个示例服务器和客户端代码,可以在gist上演示这种行为: Sample Server and Client

我怀疑当客户端连接/断开连接时,主流无法正常清理。

1 个答案:

答案 0 :(得分:4)

问题是您正在以递归方式合并Observable。每次你做

cmdStream = cmdStream.merge(socketStream);

您正在创建新的MergeObservable/MergeObserver对。

看一下source,您可以看到您基本上对每个订阅所做的事情是按顺序订阅您之前的每个流,因此不应该在周围看到它250个连接你的调用栈可能至少有1000个调用深度。

更好的方法是转换使用flatMap运算符并将您的连接视为创建Observable Observables

//Turn the connections themselves into an Observable
var connections = Rx.Observable.fromEvent(server, 'connection', 
                    socket => new JsonSocket(socket));

connections
  //flatten the messages into their own Observable
  .flatMap(socket => {
    return Rx.Observable.fromEvent(socket.__socket, 'message')
           //Handle the socket closing as well
           .takeUntil(Rx.Observable.fromEvent(socket.__socket, 'close'));
  }, (socket, msg) => { 
    //Transform each message to include the socket as well.
    return { socket : socket.__socket, data : msg}; 
  })
  .subscribe(processData, handleError);

以上我没有经过测试,但应该修复你的SO错误。

我可能也会质疑这个的整体设计。通过将所有Observable合并在一起,您究竟获得了什么?您仍然通过将套接字对象与消息一起传递来区分它们,因此看起来这些可能都是不同的流。