Node.js MySQL错误\u HTTP\u头\u已发送

Node.js MySQL错误\u HTTP\u头\u已发送,mysql,node.js,backend,Mysql,Node.js,Backend,这就是所讨论的功能: castVote: function (req, res, ip, mysql) { // POST return codes const ALREADY_VOTED = '100'; const SUCCESS = '200'; const FAILURE = '300'; // Create connection to db // Keep connection while the client is connected

这就是所讨论的功能:

castVote: function (req, res, ip, mysql) {
    // POST return codes
    const ALREADY_VOTED = '100';
    const SUCCESS = '200';
    const FAILURE = '300';

    // Create connection to db
    // Keep connection while the client is connected
    var con = mysql.createConnection({
        host: sqlHOST,
        user: sqlUSER,
        password: sqlPASS,
        database: dbNAME
    });

    // Connect to db
    con.connect(function (err) {
        // MySQL error, return
        if (err) {
            res.send(FAILURE);
            return;
        }
    });

    // Get link voted for
    var link = req.body.song_voted;

    // Check if user has already voted
    con.query(`SELECT * FROM VotedUsers WHERE ip = '${ip}'`, function (err, result, fields) {
        if (err) {
            res.send(FAILURE);
            return;
        }

        // User hasn't voted
        if (!result.length) {
            // Cast vote here
            // ...
            // Add user's IP to voted list
            con.query(`INSERT INTO VotedUsers (ip) VALUES ('${ip}')`, function (err, result) {
                if (err) {
                    res.send(FAILURE);
                    return;
                }
            });

            res.send(SUCCESS);
            return;
        }
        // User already voted
        else {
            res.send(ALREADY_VOTED);
            return;
        }
    });
}
每次用户点击一个按钮,我都会这样调用这个函数

mysql_backend.castVote(req, res, uipv4, mysql);
mysql
是mysql模块,uipv4是用户的ip)

每次我点击上述按钮,这就是错误输出:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
我有两个问题:

  • 我的代码怎么了
  • 是否有更好的方法来管理每个客户端的mysql连接(而不是在用户每次单击按钮时打开一个新的连接)

  • 1。您的代码有什么问题

    我可以看到一些东西。 首先,最明显的问题是
    con.connect
    con.query
    函数。 您没有正确地实现它们
    con.connect
    接受一个回调,一旦创建了连接,您的所有实现都应该在其中,即所有查询逻辑中

    无论如何,
    con.connect
    功能不是必需的。您可以将其删除为
    con。query
    将为您创建连接

    其次,这导致了你所看到的错误。您需要检查应用程序,以确保每个请求只调用一次
    res.send
    (或等效项)

    例如,这将抛出您看到的错误

    // User hasn't voted
    if (!result.length) {
        // Cast vote here
        // ...
        // Add user's IP to voted list
        con.query(`INSERT INTO VotedUsers (ip) VALUES ('${ip}')`, function (err, result) {
            if (err) {
                res.send(FAILURE);
                return;
            }
        });
    
        res.send(SUCCESS);
        return;
    }
    
    如果插入失败,
    res.send(SUCCESS)
    已经执行,则执行
    con.query
    回调,并调用
    res.send(FAILURE)

    这只是一个例子。您需要在整个请求中检查代码,以确保响应只发送一次。如果发送多次,您将看到发送的
    ERR\u HTTP\u HEADERS\u
    (或类似错误-取决于您在响应对象上调用的函数)。关键是你应该只发送一次回复,而且只发送一次!如果下面的问题没有解决您的错误,您需要检查应用程序的其余部分,以确保您没有再次发送响应,例如在调用
    mysql\u backend.castVote(req、res、uipv4、mysql)之后

    解决上述问题取决于预期的结果

    如果要向调用方返回发生错误的消息,则必须等待回调返回。e、 g

    if (!result.length) {
        // Cast vote here
        // ...
        // Add user's IP to voted list
        con.query(`INSERT INTO VotedUsers (ip) VALUES ('${ip}')`, function (err, result) {
            if (err) {
                res.send(FAILURE);
                return;
            }
            res.send(SUCCESS);
            return;
        });
    }
    
    2。是否有更好的连接管理方法

    是-使用。连接池允许您限制可以创建的连接数,例如,如果您有100个并行请求,且最大池大小为10,则您将只能创建10个连接