在使用takeUntil()和Observable.fromEvent()方法时需要帮助

时间:2018-07-16 20:42:41

标签: node.js rxjs

我正在跟踪this tutorial在Node.js中创建响应式TCP服务器

这是我一直在努力的代码

const Rx = require('rxjs')
const net = require('net')
const uuid = require('uuid');

module.exports  = () => {

        const sockets = new Map();
        const ids = new Map();

        const GetSocket = _id => sockets.get(_id);
        const GetId = _socket => ids.get(_socket);

        const SetSocket = _socket =>{
            _socket.setEncoding('utf8');

            const _id = uuid();
            sockets.set(_id, _socket);
            ids.set(_socket,_id);
            return _id;
        };

        const server = net.createServer({ allowHalfOpen: true });
        const socketStream = Rx.Observable.fromEvent(server, 'connection');

        const RemoveSocket = socket = () => {
            console.log("connection closed && removing socket from Map");
            const id = ids.get(socket);
            sockets.delete(id);
            ids.delete(socket)
        };
        const socketObservable = socket => SetSocket(socket) &&
            Rx.Observable
            .of({
                action: 'CONNECTION',
                socket: GetId(socket)
            })
                .merge(
                Rx.Observable
                    .fromEvent(socket,'data')
                    .map(d=>{
                        try {return JSON.parse(d);}
                        catch (e) {
                            console.log(e);
                            return d;
                        }
                    })
                    .map(msg=>{
                        return Object.assign({action:msg,socket:GetId(socket)})
                    })
                )
            .takeUntil(Rx.Observable.fromEvent(socket, 'close').map(d=>{
                console.log("!!!! Should remove !!!");
                RemoveSocket(socket);
            }));

        const Print = ()=>{
            //ids.forEach(id=> console.log(GetSocket(id)));
            console.log("total connected socket : " + ids.size);
        };

        const startServer = port => server.listen(port) &&
            socketStream
                .flatMap(socketObservable);
        
        return {startServer, Print , stop: () => server.close()};
    };

这是我的测试结果(只需发送测试消息并连接/重新连接到服务器)

{ action: 'CONNECTION',
  socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: { test: 1 },
  socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: { test: 2 },
  socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: 'CONNECTION',
  socket: 'b868104b-d1cf-41c9-950f-472f63bac27a' }
total connected socket : 2
{ action: { test: 1 },
  socket: 'b868104b-d1cf-41c9-950f-472f63bac27a' }
total connected socket : 2
{ action: 'CONNECTION',
  socket: 'b9a579fe-3715-4952-aaf7-d7f64a0bea99' }
total connected socket : 3

一切正常,直到通过 TakeUntil()检测到套接字关闭事件为止 我尝试使用 takewhile(),只需添加类似 TakeWhile(cnt <5)的计数器 和套接字流按预期完成。

这是我第一次尝试使用Node.js制作东西,感觉好像我错过了一些东西。

有人可以帮助我了解为什么takeUntil()在这里不起作用吗? 谢谢:)

1 个答案:

答案 0 :(得分:0)

所以我的困惑来自于理解'close''end'事件

服务器接收到FIN packet时,客户端断开连接或服务器调用'end'时,会触发

socket.end(..)事件

'close'事件在socket.destroy()

之后被调用

如果有人想查看所有套接字事件,我建议观看this video

@Brannon,感谢您指出正确的事件用法,并感谢大家为我提供帮助!

以防万一,任何人都想使用TCP服务器代码。

依赖性:rxjs 5.5.0

const Rx = require('rxjs');
const net = require('net');
const uuid = require('uuid');

module.exports  = () => {

    const sockets = new Map();
    const ids = new Map();

    const GetSocket = _id => sockets.get(_id);
    const GetId = _socket => ids.get(_socket);

    const SetSocket = _socket =>{
        _socket.setEncoding('utf8');
        const _id = uuid();
        sockets.set(_id, _socket);
        ids.set(_socket,_id);
        return _id;
    };

    const server = net.createServer({ allowHalfOpen: true });
    const socketStream = Rx.Observable.fromEvent(server, 'connection');

    const RemoveSocket = socket  => {

        const id = ids.get(socket);
        sockets.delete(id);
        ids.delete(socket)

        console.log("[server.js] socket closed..");
    };
    const socketObservable = socket => SetSocket(socket) &&
        Rx.Observable
            .of({
                action: 'CONNECTION',
                socket: GetId(socket)
            })
            .merge(
                Rx.Observable
                    .fromEvent(socket,'data')
                    .map(d=>{
                        try {return JSON.parse(d);}
                        catch (e) {
                            console.log(e);
                            return d;
                        }
                    })
                    .map(msg=>{
                        return Object.assign({action:msg,socket:GetId(socket)})
                    })
            )
            .takeUntil(Rx.Observable.fromEvent(socket, 'end')
                .map(()=>RemoveSocket(socket)));

    const Print = ()=>{
        //ids.forEach(id=> console.log(GetSocket(id)));
        //ids.clear();
        console.log("total connected socket : " + ids.size);
    };

    const startServer = port => server.listen(port) &&
        socketStream
            .flatMap(socketObservable);

    console.log("[server.js] Starts Started" );
    return {startServer, Print , stop: () => server.close()};
};