首页 > 解决方案 > 使用nodejs mysql将标头发送到客户端后无法设置标头

问题描述

我正在尝试做的是编写一个语句来检查用户注册时我的 mysql 数据库中是否存在电子邮件。在邮递员中,它向我发送了“用户已被占用”的正确错误消息,但是服务器在之后崩溃并显示“在将标头发送到客户端后无法设置标头”。我读过类似的帖子,但没有帮助。

//The following code is in my user.service.js file:

const pool = require("../../config/database");

module.exports = {

  //Create new user
  createUser: (data, callBack) =>{
    pool.query(
      `insert into registration(name, email, password, confirm_password)
              values(?,?,?,?)`,
    [
      data.name,
      data.email,
      data.password,
      data.confirm_password
    ],
    (error, results, fields) =>{
      if(error){
        return callBack(error);
      }
      return callBack(null, results);
    }
    );
  }
}

//以下代码在我的 user.controller.js 文件中:

const {
  createUser,
} = require("./user.service");
const pool = require("../../config/database");


module.exports = {
  
  createUser: (req, res) =>{
    const body = req.body;
    const salt = genSaltSync(10);
  pool.query('SELECT email FROM registration WHERE email = ?', [body.email], (error, results) =>{
    if(error){
      console.log(error);
    }
    if(results.length > 0){
      return res.status(400).json({
        message: 'User already taken'
      })
    }
  })
    createUser(body, (err, results) => {
      if(err){
        console.log(err);
        return res.status(500).json({
          success:0,
          message:"Error in database connection"
        });
      }
      return res.status(200).json({
        success: 1,
        message: `User ${results.insertId} signed up successfully`,
        data: results
      });
    });
  }

}

//以下代码来自user.router.js文件:

const {
  createUser,
} = require("./user.controller");
const router = require("express").Router();

router.post("/signup", createUser);

module.exports = router;

标签: javascriptmysqlnode.jsapiexpress

解决方案


在您createUser在发布请求上执行的函数中,您正在做两件事。首先,您检查是否存在具有所提供电子邮件的用户,然后,您创建一个用户。但是,这些函数不是连续执行的,而是同时运行的,因此会产生竞争条件。

因此,继续您的示例,如果电子邮件检查查询SELECT email FROM registration WHERE email = ?更快并且用户已经存在,它将响应:

  return res.status(400).json({
    message: 'User already taken'
  })

createUser函数(如下)仍在运行,一旦完成,它也会尝试发送响应。因此,您会在控制台中看到应用程序崩溃,即使在邮递员中您可以看到说明用户已经存在的响应。

为了修复此错误,您应该createUser仅在提供给电子邮件检查查询的回调中执行该函数,如下所示results.length0

createUser: (req, res) => {
    const body = req.body;
    const salt = genSaltSync(10);
  pool.query('SELECT email FROM registration WHERE email = ?', [body.email], (error, results) =>{
    if(error){
      console.log(error);
    }

    if(results.length > 0){
      return res.status(400).json({
        message: 'User already taken'
      })
    }

    createUser(body, (err, results) => {
      if(err){
        console.log(err);
        return res.status(500).json({
          success:0,
          message:"Error in database connection"
        });
      }
      return res.status(200).json({
        success: 1,
        message: `User ${results.insertId} signed up successfully`,
        data: results
      });
    });
  })
}

现在,createUser仅当具有所提供电子邮件的用户不存在时才执行该函数,这有效地消除了两个函数之间的竞争条件。


推荐阅读