Reputation: 329
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
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