Ошибка: невозможно установить заголовки после их отправки. ошибка получена после обновления запроса на получение - PullRequest
0 голосов
/ 04 июля 2018

Следующий код работает, как и ожидалось, при первом запуске. Второй раз через него происходит сбой со следующей ошибкой:
Error: Can't set headers after they are sent.
По сути, я пытаюсь вернуть сообщение из серии опубликованных тем mqtt. Я пробовал несколько способов сделать это, но затрудняюсь с этим поведением. Приведенный ниже код демонстрирует попытку использования обещаний, как описано в этой статье MDN. Я также попытался использовать async / await (я также могу опубликовать этот код при необходимости).

Концепция
с веб-страницы поступает запрос на получение, что приводит к публикации mqtt-сообщения локальному брокеру. отдельная конечная точка слушает эту тему. В этом случае малиновый пи с подключенной веб-камерой. Тема получена, rpi делает свое дело и публикует ответное сообщение с URL-адресом в качестве данных. первоначальный издатель mqtt прослушивает этот ответ и запускает res.json () в ответ.
Это работает в первый раз, когда я обновляю веб-страницу, она перестает работать с заголовками Can't после их отправки. Как сделать один сброс? Похоже, что это так.

punchitRoute.js

const express = require('express');
const punchitRoute = express.Router();
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://192.168.88.54:1883');

client.subscribe('returned', function(){
    console.log('subscribed');
})

async function img(){
    return new Promise(resolve =>{ client.on('message', function(topic, url){
            const message = {
                url: url.toString(),
                name: "garfield",
                date: Date.now()
            }
        return message;
        })
     })

}

 punchitRoute.get('/', async function(req, res){
    const mess = await img();
    console.log(mess);
    res.json(mess);
});

module.exports = punchitRoute;

server.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const punchit = require('./routes/punchitRoute');


app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended:false })); 

app.get("/", (req, res) => {

    res.json({
      name: "Express application",
      message: "welcome to punchit"
    })
  });

app.use('/api/punchit', punchit);

  const PORT = process.env.PORT || 6040;
  app.listen(PORT);
  console.log('server started on: ', PORT);

Я предполагаю, что мне не хватает базового факта жизни, касающегося запросов с использованием экспресс.
Заранее спасибо за любые рекомендации.

1 Ответ

0 голосов
/ 08 июля 2018

Спасибо jfriend00 за указание в правильном направлении. Сначала опубликованный код был совершенно неверным. Я был очень смущен этим и впоследствии переименовал файл punchitRoute, чтобы продолжить работу с ним другим способом, но забыл переименовать нужный файл в server.js! Это была глупая ошибка.

Второй комментарий о обработчике события для client.on('message', ...) дал мне подсказку, необходимую для просмотра цикла событий.

Идея состояла в том, чтобы привязать изображение с веб-камеры с помощью mqtt из запроса get. Запрос get поступает на экспресс-сервер, вызывает подписку на тему с именем ' return' и публикуется в теме с именем ' sunrise' с сообщением 'click' .

Существует отдельная конечная точка в локальной сети, которая прослушивает локального брокера mqtt (оба совместно используемого с экспресс-сервером), который прослушивает тему 'sunrise' . Эта конечная точка вещания «вернула» после того, как изображение было сохранено в корзину S3, и отправило URL-адрес изображения в качестве сообщения обратно на сервер, выполняющий запрос get. Функции mqtt работают хорошо, у меня была проблема с событием ответа, которое не заканчивалось при завершении ответа. Для этого тоже нужно было изменить несколько вещей.

  1. переместил res.send в функцию, вызываемую после client.on (это не сработало полностью, это позволило выполнить отправку, но все равно вернуло ошибку)
  2. добавлены источники событий, чтобы увидеть, какое событие вызывалось снова и снова (это дало мне некоторое представление о происходящем, но все равно не устранило ошибку)
  3. исследовал дополнительные библиотеки mqtt (в итоге остановился на async-mqtt)
  4. добавлен client.unsubscribe для обеих тем после функции res.send (это не имело никакого эффекта)
  5. наконец нашел этот ответ, который помог мне понять все это время, которое я мог просто позвонить client.once!

вот код запроса на получение:

punchitRoute.get('/', async function(req, res){
//adding event listner 'send'
mqEvent.on('send', function(){
    console.log('added send');
});

let sendit = function(url){
    'send', //emmitting 'send'
    res.status(200).send(
        '<img src='+url.toString()+' />'+
        '<h1>PUNCHED!</h1>'+
        '<p>'+
        'name: garfield <br/> time: '+moment(Date.now()).tz("America/Louisville").format('MM-DD-YYYY'));
    }

client.subscribe('returned', function(){
    console.log('subscribed');
});
client.publish('sunrise', 'click');
//changed this to .once and no more errors
await client.once('message', async function callout(topic, url){
    try {

            mqEvent.on('message', function(){
                console.log('added message');
            });

        sendit(url.toString());

            // console.log(res);
        client.unsubscribe('returned', ()=>{
            console.log('unsubscribed');
        });
        client.unsubscribe('sunrise', ()=>{
            console.log('unsubscribed publish');
        });
        //clearing out the send event listeners
        mqEvent.removeAllListeners('send');
        console.log(mqEvent.listenerCount('send'));
        //clearing out the message event listeners
        mqEvent.removeAllListeners('message');

     } catch(e){
            console.log(e);
            console.log('error');
        }
    })
});

Надеюсь, это может кто-то другой столкнулся с подобной проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...