Need help on using takeUntil() and Observable.fromEvent() Methods

只谈情不闲聊 提交于 2019-12-13 03:14:58

问题


I'm following this tutorial to create Reactive TCP server in Nodejs

here's code that i've been working on

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()};
    };

and here's my test result(just sending test msg and connect/reconnect to server )

{ 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

Everything working fine till detecting socket close event by TakeUntil() I tried using takewhile() by simply adding counter like this TakeWhile(cnt < 5) and socket stream completed as expected.

this is my first attempt to make something with Node.js and feel like i'm missing something.

can anyone help me to understand why takeUntil() is not working here? Thank you :)


回答1:


So my confusion was from understanding 'close' and 'end' events

'end' event gets triggered when the client disconnected or server calls socket.end(..) when server receives FIN packet

and 'close' event gets called after socket.destroy()

if anyone wants to see all socket events in action, I recommend watching this video

@Brannon, Thank you for pointing out the right event usage and thank you, everyone, for helping me out with this!!

also just in case, anyone wants working TCP server code.

dependency : 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()};
};


来源:https://stackoverflow.com/questions/51369830/need-help-on-using-takeuntil-and-observable-fromevent-methods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!