使用 mysql2 async/await 时出现“发送给客户端后无法设置 headers” 错误

`Cannot set headers after they are sent to client` error when using mysql2 async/await

我正在更改我的后端(从 Mongo 切换到 MySql)。我知道会抛出错误,因为 return 语句在我的 SQL 查询完成之前执行,然后当我的 sql 查询完成时,它会发送另一个 res.send ,因此我尝试将 mysql2 与 Promise 包装器一起使用,以便在我的 async 函数中的查询中使用 await

我有一个创建数据库连接的单独文件,因此我可以在整个 Nodejs 后端访问该连接:

const mysql = require('mysql2');

async function pool(){
    const pool = await mysql.createPool({
        host: "ip",
        user: "username",
        password: "password",
        database: "db"
    });
    return pool
}

exports.getConnection = async function(callback) {
    const currentPool = await pool();
    currentPool.getConnection(function(err, conn) {
        if(err) return callback(err);
        callback(err,conn)
    });
};

然后,创建一个遵循 async/await:

的查询
sql.getConnection(async function(err, client){
        client.query(`select email from users where email = "${email}"`, function (error, result){
            if(error) return res.status(500).send('an internal db error occurred');
            // carry on with code ...
    });
});

我也试过在查询中使用 await:

await sql.getConnection(async function(err, client){
        client.query(`select email from users where email = "${email}"`, function (error, result){
            if(error) return res.status(500).send('an internal db error occurred');
            // carry on with code ...
    });
});

我错过了什么?我还没有厌倦使用普通的 mysql NPM 库并制作我自己的 promise 包装器...

新代码:

我更新了我的功能:

const mysql = require('mysql2');

const pool = mysql.createPool({
    host: "ip",
    user: "user",
    password: "pass",
    database: "db"
});

exports.db = (sql) => {
    new Promise((resolve, reject) => {
        pool.getConnection((err, conn) => {
            if(err) return reject(err);

            conn.query(sql, (err, results, fields) => {
                conn.release()
                if(err) return reject(err)
                console.log(results)
                resolve(results);
            });
        });
    });
}

然后我通过以下方式调用它:

try{
    const emailExisit = await sql.db(`SELECT email FROM users WHERE email = "${email}"`);
    console.log(emailExisit);
    if(emailExisit.length > 0) return res.status(422).send({"data": "", "code": "105", "message": "An account with given email already exists"});
}catch (err) {
    console.log(err)
    return res.status(500).send({"data": "", "code": "108",  "message": `There seems to be an error contacting the database. Try again later <br> ${err}`});
}

但是,我的代码仍在继续,留下我的 emailExists 变量 undefined(是的,它在 async function 中)

这是我使用 MySQL 和 Node.js 的配置。希望对你有用。

/config/mysql.js

const mysql = require('mysql2');

const pool = mysql.createPool({
  host: process.env.MYSQL_HOST,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
  port: process.env.MYSQL_PORT,
  database: process.env.MYSQL_DB_NAME,
});

const query = (query, args = []) =>
  new Promise((resolve, reject) => {
    pool.getConnection((err, connection) => {
      if (err) {
        return reject(err);
      }
      connection.query(query, args, (err, results) => {
        connection.release();
        if (err) {
          return reject(err);
        }
        resolve(results);
      });
    });
  });

module.exports = { query };


/index.js

const { query } = require('./mysql');
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded());

app.get('/api/v1/sum', (req, res) => {
  query('SELECT 1 + 1 as sum')
    .then(results => {
      res.json({ sum: results[0].sum });
    })
    .catch(err => {
      console.error(err);
      res.status(500).json({ error: 'error msg' });
    });
});

// anther example with async
app.get('/api/v1/sum', async (req, res) => {
  try {
    const results = await query('SELECT 1 + 1 as sum');
    res.json({ sum: results[0].sum });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'error msg' });
  }
});

app.listen(3000);