首页 > 解决方案 > 在 node.js express 中返回响应的正确方法是什么?

问题描述

我无法理解我的代码有什么问题。我正在创建简单的 node.js REST api,无论我做什么都会出错:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:535:11)
    at ServerResponse.header (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\express\lib\response.js:771:10)
    at ServerResponse.send (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\express\lib\response.js:267:15)
    at Query.<anonymous> (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\controllers\users.js:38:32)
    at Query.<anonymous> (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\mysql\lib\Connection.js:526:10)
    at Query._callback (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\mysql\lib\Connection.js:488:16)
    at Query.Sequence.end (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
    at Query._handleFinalResultPacket (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\mysql\lib\protocol\sequences\Query.js:149:8)
    at Query.EofPacket (D:\04. MOJE\08. STUDIA\6 semestr\Wybrane technologie webowe\Projekt\silicon store api\node_modules\mysql\lib\protocol\sequences\Query.js:133:8) {
  code: 'ERR_HTTP_HEADERS_SENT'

导致错误的代码如下:

exports.register = function (req, res) {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() });
  }

  var userId;
  // check whether email is taken
  mysql.query(
    'SELECT email FROM users where email = ?',
    [req.body.email],
    (err, rows, fields) => {
      if (err) {
        return res.sendStatus(500);
      }
      if (rows.length > 0) {
        return res.status(400).json({
          message: 'Mail taken',
        });
      }
    }
  );
  // check whether name is taken
  mysql.query(
    'SELECT name FROM users where name = ?',
    [req.body.name],
    (err, rows, fields) => {
      if (err) {
        return res.status(500);
      }
      if (rows.length > 0) {
        return res.status(400).json({
          message: 'Name taken',
        });
      }
    }
  );

其中第 38 行是:

return res.status(400).json({ message: 'Name taken' });

但是响应是正确的,我收到错误 400,error设置为Mail taken

据我了解,这与尝试多次发送响应有关。在检查姓名或电子邮件是否被占用后,注册功能不会结束。那里有更多的代码,但原理是一样的。

我不知道也无法在网上找到任何信息,什么是处理响应的正确方法。

标签: javascriptnode.jsexpress

解决方案


您要返回两次响应,这会导致cannot set headers错误。您需要在第mysql.query一个回调函数中运行第二个。或者,您可以使用async await.

exports.register = function (req, res) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(422).json({ errors: errors.array() });
    }

    var userId;
    // check whether email is taken
    mysql.query(
        'SELECT email FROM users where email = ?',
        [req.body.email],
        (err, rows, fields) => {
            if (err) {
                return res.sendStatus(500);
            }
            if (rows.length > 0) {
                return res.status(400).json({
                    message: 'Mail taken',
                });
            }
            // check whether name is taken
            mysql.query(
                'SELECT name FROM users where name = ?',
                [req.body.name],
                (nameErr, nameRows, fields) => {
                    if (nameErr) {
                        return res.status(500);
                    }
                    if (nameRows.length > 0) {
                        return res.status(400).json({
                            message: 'Name taken',
                        });
                    }
                    // if no errors, run the rest of your code here
                }
            );
        }
    );
}


推荐阅读