NodeJS: Как я могу обновить представление с несколькими ответами от подписанного веб-сокета?
Я новичок в паутине.
Я пытаюсь реализовать веб-сокет в приложении MeanJS, чтобы подписаться на некоторые данные в реальном времени, которые предоставляет другой веб-сайт, когда данные будут возвращены, я бы хотел обновить таблицу в моем представлении с результатами.
Я столкнулся с логической проблемой. Моя реализация не удалась, потому что она пытается отправить несколько ответов через одно соединение TCP (я полагаю), она умирает с ошибкой:
throw new Error('Cant set headers after they are sent.');
Я понимаю, почему возникает эта ошибка, но, будучи новичком в WebSockets и довольно новым для NodeJS, я не уверен, как реорганизовать этот код таким образом, который имеет смысл.
В моем клиентском контроллере:
// Get Orderbook
$scope.getOrderbook = function() {
$http.get('exchanges/' + $stateParams.exchangeId + '/get_orderbook')
.success(function(data) {
console.log("ORDERBOOK DATA: " + data); // DEBUGGING
$scope.orderBook = data;
});
};
В моем контроллере на стороне сервера:
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);
}
});
}
};
Каков наилучший способ рефакторинга этого кода, чтобы я мог подписаться на веб-сокет, получать от него сообщения, а при получении любого сообщения обновлять представление данными?
1 ответ
При каждом новом входящем HTTP-запросе вы пытаетесь открыть новый веб-сокет для какого-либо сайта, а затем каждый раз, когда получаете сообщение, пытаетесь отправить ответ. Между тем, вы никогда не закрываете свою веб-розетку.
Особая ошибка возникает, когда вы пытаетесь отправить второй http-ответ на тот же http-запрос, когда первый ответ уже отправлен. Это произойдет в вашем коде, когда вы получите второе сообщение на веб-сокете.
Кроме того, вы открываете новый веб-сокет каждый раз, когда получаете этот запрос, который просто приводит к накоплению этих открытых веб-сокетов.
Если вам действительно нужно использовать веб-сокет для получения ваших данных, то вам нужно закрыть веб-сокет, как только вы получите ваше первое сообщение, или удалить эти обработчики событий, связанные с конкретным запросом.
Вот один из способов сделать это:
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
}
};