Ошибка [ERR_HTTP_HEADERS_SENT]: не удается установить заголовки после их отправки клиенту, при выполнении запроса к API

#node.js #postgresql #express

#node.js #postgresql #выразить

Вопрос:

Я продолжаю получать эту ошибку в своем терминале после того, как я делаю запрос к API

 [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:518:11)
    at ServerResponse.header (D:GitHubObsidion-Dashboardnode_modulesexpresslibresponse.js:771:10)
    at ServerResponse.send (D:GitHubObsidion-Dashboardnode_modulesexpresslibresponse.js:170:12)
    at ServerResponse.json (D:GitHubObsidion-Dashboardnode_modulesexpresslibresponse.js:267:15)
    at D:GitHubObsidion-Dashboardapidatabase.js:169:36
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
 

Мой маршрутизатор выглядит так

 router.get('/prefix', (req, res) => {
    if (!req.query.token) throw new Error('NoTokenProvided');
    if (!req.query.guildid) throw new Error('NoGuildIDProvided');
    const token = req.query.token;
    const guildid = req.query.guildid;

    var sql = `SELECT token FROM auth WHERE token='${token}'`;

    db.all(sql, [], (err, rows) => {
        if (err) {
            throw new Error("ErrorWithDatabase");
        }

        if (rows.length === 0) {
            res.json({code: 401, "message": "That is not a valid token."})
        }

        rows.forEach((row) => {
            if (row.token === token) {
                pool.query(`SELECT prefix FROM guild WHERE id='${guildid}'`)
                .then(response => {
                    // console.log(response.rows[0].prefix)
                    if (!response.rows[0]) {
                        return res.json({code: 200, "message": "User has not setup a custom prefix."})
                    } else {
                        return res.json({code: 200, "prefix": response.rows[0].prefix})
                    }
                })
                .catch(e => console.error(e))
            } else {
                res.json({code: 401, "message": "That is not a valid token."})
            }
        })

    });
})
 

Он не должен пытаться отправлять заголовки на маршрутизатор после того, как я вернул res.json. Он подключается к базе данных postgresql и, похоже, подключается к ней просто отлично.

Комментарии:

1. Вы пытаетесь отправить ответ внутри a .forEach() , что означает, что вы будете пытаться отправить более одного ответа на запрос. Я не могу этого сделать.

2. @jfriend00 Вместо этого вы должны добавить ответ

Ответ №1:

Вы пытаетесь отправить ответ внутри a .forEach() , что означает, что вы будете пытаться отправить более одного ответа на запрос. Не удается этого сделать. Вы можете отправлять один ответ на каждый входящий запрос.

Если вы хотите просто отправить первый соответствующий ответ, затем измените .forEach() его на обычный for цикл, а затем, когда вы вернетесь, он завершит цикл.

Если вы хотите отправить несколько ответов, то вам нужно собрать все результаты в локальный массив, а затем отправить их все в конце. И, поскольку вы используете асинхронные операции внутри цикла, вам придется либо использовать await для приостановки цикла, либо использовать Promise.all() для сбора всех асинхронных результатов и узнать, когда все они будут выполнены.


К вашему сведению, в наши дни асинхронного программирования и переменных с блочной областью действия я бы счел .forEach() их устаревшими, потому for что цикл превосходит их во всех отношениях. У него есть возможность использовать await и фактически приостанавливать цикл , и он обладает превосходным управлением потоком , поскольку вы можете break , continue или return — ничего из этого вы не можете сделать .forEach() .

Комментарии:

1. Добавлено дополнительное примечание о .forEach() том, что сейчас оно в значительной степени устарело.