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
    }
};
Другие вопросы по тегам