Dave Rich
Dave Rich

Reputation: 329

NodeJS: How can I update the view with multiple responses from subscribed websocket?

I am new to websockets.

I am trying to implement a websocket in a MeanJS application to subscribe to some realtime data that another website provides, when data gets returned I'd like to update a table in my View with the results.

I've run into a logical issue. My implementation failed because it is trying to send multiple responses over a single tcp connection (I believe), it dies with the error:

throw new Error('Cant set headers after they are sent.');

I understand why this error is occuring, but being new to WebSockets and fairly new to NodeJS I'm not sure how to refactor this code in a manner that makes sense.

In My Clientside Controller:

    // Get Orderbook
    $scope.getOrderbook = function() {
        $http.get('exchanges/' + $stateParams.exchangeId + '/get_orderbook')
            .success(function(data) {
                console.log("ORDERBOOK DATA: " + data); // DEBUGGING
                $scope.orderBook = data;
            });
    };

In My Server Side Controller:

    exports.getOrderbook = function(req, res, next) {
        var exchange = req.exchange;

        if(exchange.slug === 'somesite') {
            var ws = new WebSocket('wss://www.somesite.com/realtimews');

            ws.on('open', function open() {
                ws.send('{"op": "subscribe", "args": "orderBook"}');
            });

            ws.on('message', function(message) {
                var response = JSON.parse(message);

                if(response.table) {
                    res.jsonp(response.data);
                }
            });
        }
    };

What's the best way to refactor this code so that I can subscribe to the websocket, receive messages from it, and when any message is received update the view with the data?

Upvotes: 0

Views: 572

Answers (1)

jfriend00
jfriend00

Reputation: 707786

On each new incoming http request, you are trying to open a new websocket to some site and then each time you get a message you are trying to send a response. Meanwhile, you never close your websocket.

The particular error you get happens when you try to send a second http response to the same http request when the first response has already been sent. This will happen in your code when you get a second message on the websocket.

In addition, you open a new websocket everytime you get this request which just makes these open websockets accumulate.

If you really have to use a websocket to get your data, then you need to close the websocket as soon as you've gotten your first message or remove these event handlers that are associated with a particular request.

Here's one way to do it:

exports.getOrderbook = function(req, res, next) {
    var exchange = req.exchange;

    if(exchange.slug === 'somesite') {
        var ws = new WebSocket('wss://www.somesite.com/realtimews');

        ws.on('open', function open() {
            ws.send('{"op": "subscribe", "args": "orderBook"}');
        });

        ws.on('message', function(message) {
            var response = JSON.parse(message);

            if(response.table) {
                res.jsonp(response.data);
            } else {
                res.jsonp(/* some error response here */)
            }
            // close the websocket so we don't associate any more responses
            // with this particular http request
            ws.close();                
        });
    } else {
        // need to send some response here
    }
};

Upvotes: 0

Related Questions