【问题标题】:Node JS and Sequelize Error: Cannot set headers after they are sent to the clientNode JS 和 Sequelize 错误:在将标头发送到客户端后无法设置标头
【发布时间】:2021-06-02 13:07:40
【问题描述】:

当我尝试执行查询以将用户名从 id 获取到控制器时出现此错误。我已尝试解决此问题,但没有解决方案,有没有办法通过查询获取用户名?

用户模型:

'use strict';
const {
  Model
} = require('sequelize');
const config = require('../config');
module.exports = (sequelize, DataTypes) => {
  class tb_user extends Model {

    static associate(models) {
    }
  };
  tb_user.init({
    id_user:{
      type:DataTypes.INTEGER,
      primaryKey:true,
      autoIncrement:true
    },
    username: DataTypes.STRING,
    email: DataTypes.STRING,
    password: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'tb_user',
    freezeTableName:true
  });

  tb_user.associate = models =>{
    tb_user.hasMany(models.tb_tech,{
      foreignKey:'id_user',
      as:'tb_tech',
      onDelete:'CASCADE'
    })
  }
  return tb_user;
};

主管模型:

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class tb_supervisor extends Model {

    static associate(models) {
    }
  };
  tb_supervisor.init({
    id_supervisor:{
      type:DataTypes.INTEGER,
      primaryKey:true,
      autoIncrement:true
    },
    username: DataTypes.STRING,
    email: DataTypes.STRING,
    password: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'tb_supervisor',
    freezeTableName:true
  });

  tb_supervisor.associate = models =>{
    tb_supervisor.hasMany(models.tb_tech,{
      foreignKey:'id_supervisor',
      as:'tb_tech',
      onDelete:'CASCADE'
    })
  }
  return tb_supervisor;
};

技术员模型:

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class tb_tech extends Model {
    static associate(models) {
    }
  };
  tb_tech.init({
    id_tech:{
      type:DataTypes.INTEGER,
      primaryKey:true,
      autoIncrement:true
    },
    id_user: DataTypes.INTEGER,
    id_supervisor: DataTypes.INTEGER,
    zone:DataTypes.INTEGER,
    region:DataTypes.INTEGER,
    full_name: DataTypes.STRING,
    tech_type: DataTypes.STRING,
    goal: DataTypes.FLOAT,
    observations: DataTypes.STRING,
    client: DataTypes.STRING
  }, {
    sequelize,
    modelName: 'tb_tech',
    freezeTableName:true
  });

  tb_tech.associate = models =>{
    tb_tech.belongsTo(models.tb_user,{
      foreignKey:'id_user',
      as:'tb_user',
      onDelete:'CASCADE'
    })

    tb_tech.belongsTo(models.tb_supervisor,{
      foreignKey:'id_supervisor',
      as:'tb_supervisor',
      onDelete:'CASCADE'
    })
  }

  return tb_tech;
};

主管控制器:

const Supervisor = require("../models").tb_supervisor;
const Tecnico = require("../models").tb_tech;
const Usuario = require("../models").tb_user;

module.exports = {
   getAllSupervisors(req,res){
        const id_supervisor = req.params.id_supervisor;
        return Supervisor
                .findAll({
                    include:[{
                        model:Tecnico, as:'tb_tech',
                        where:{
                            id_supervisor:id_supervisor
                        }
                    }]
                })
                .then(sup => {
                    const resObj = sup.map(supervisor => {
                        return Object.assign(
                            {},
                            {
                                id_supervisor : supervisor.id_supervisor,
                                username: supervisor.username,
                                email: supervisor.email,
                                technician: supervisor.tb_tech.map(tec => {
                                    return Object.assign(
                                        {},
                                        {
                                            tech_id : tec.id_tech,
                                            id_user: Usuario.findOne({
                                                where:{
                                                    id_user:tec.id_user
                                                },
                                                attributes:['username']
                                            }).then(user => res.json(user)).catch(error => console.log(error)),
                                            id_supervisor: tec.id_supervisor,
                                            zone: tec.zone,
                                            region: tec.region,
                                            full_name: tec.full_name,
                                            tech_type:tec.tech_type,
                                            goal: tec.goal,
                                            observations: tec.observations,
                                            client: tec.client
                                        }
                                    )
                                })
                            }
                        )
                    })
                    res.status(200).json(resObj);
                })
                .catch(error => {
                    res.status(500).send({message:error.message});
                })
    },
}

路线:

const router = require('express').Router();
const UsuarioController = require("../controllers/user");
const TecnicoController = require("../controllers/tech");
const SupervisorController = require("../controllers/supervisor");

router.use(function(req,res,next){
    res.header(
        "Access-Control-Allow-Headers",
        "x-access-token, Origin, Content-Type, Accept",
        "Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE",
        "Access-Control-Allow-Origin", "*"
    );
    next();
});

router.get('/users/getAllUsers/:id_user',UsuarioController.getAllUsers);

router.get('/supervisor/getAllSupervisors/:id_supervisor',SupervisorController.getAllSupervisors);

router.get('/techs/getAllTechs',TecnicoController.getAllTechs);

module.exports = router;

在邮递员中,查询很好,但我需要用户名的字段是空白对象,控制台抛出以下错误。可以在另一个查询中进行查询吗?

图片:

问题是,错误的根源是什么?您可以在另一个查询中进行查询吗?。

非常感谢您。

【问题讨论】:

    标签: node.js express sequelize.js


    【解决方案1】:

    顾名思义,这是因为您尝试发送响应标头的次数超过一次,即不可能在第一和第二位,尝试根据 nodejs 的异步行为更改您的代码使用 async await 来避免函数链接避免在数组的 map、filter 和其他异步函数中进行异步调用,因为它们不会等待使用原生或 for 循环来代替

    module.exports = {
      getAllSupervisors(req, res) {
        const id_supervisor = req.params.id_supervisor;
        return Supervisor.findAll({
          include: [
            {
              model: Tecnico,
              as: "tb_tech",
              where: {
                id_supervisor: id_supervisor
              }
            }
          ]
        })
          .then((sup) => {
            const resObj = sup.map((supervisor) => {
              return Object.assign(
                {},
                {
                  id_supervisor: supervisor.id_supervisor,
                  username: supervisor.username,
                  email: supervisor.email,
                  technician: supervisor.tb_tech.map((tec) => {
                    return Object.assign(
                      {},
                      {
                        tech_id: tec.id_tech,
                        id_user: Usuario.findOne({
                          where: {
                            id_user: tec.id_user
                          },
                          attributes: ["username"]
                        })
                          .then((user) => res.json(user)) // sending response here for first time
                          .catch((error) => console.log(error)),
                        id_supervisor: tec.id_supervisor,
                        zone: tec.zone,
                        region: tec.region,
                        full_name: tec.full_name,
                        tech_type: tec.tech_type,
                        goal: tec.goal,
                        observations: tec.observations,
                        client: tec.client
                      }
                    );
                  })
                }
              );
            });
            res.status(200).json(resObj); //for second time
          })
          .catch((error) => {
            res.status(500).send({ message: error.message });
          });
      }
    };
    

    为避免这种情况,请尝试这样做

    module.exports = {
      async getAllSupervisors(req, res) {
        const id_supervisor = req.params.id_supervisor;
        const sub = await Supervisor.findAll({
          include: [
            {
              model: Tecnico,
              as: "tb_tech",
              where: {
                id_supervisor: id_supervisor
              }
            }
          ]
        });
        // const resObj = sup.map((supervisor) => {
        const resObj = [];
        for (const supervisor of sub) {
          resObj.push(
            Object.assign(
              {},
              {
                id_supervisor: supervisor.id_supervisor,
                username: supervisor.username,
                email: supervisor.email,
                technician: supervisor.tb_tech.map((tec) => {
                  return Object.assign(
                    {},
                    {
                      tech_id: tec.id_tech,
                      id_user: await Usuario.findOne({
                        where: {
                          id_user: tec.id_user
                        },
                        attributes: ["username"]
                      }),
                      id_supervisor: tec.id_supervisor,
                      zone: tec.zone,
                      region: tec.region,
                      full_name: tec.full_name,
                      tech_type: tec.tech_type,
                      goal: tec.goal,
                      observations: tec.observations,
                      client: tec.client
                    }
                  );
                })
              }
            )
          );
        }
        // });
        res.status(200).json(resObj); //second
        res.status(500).send({ message: error.message });
      }
    };
    
    

    【讨论】:

      【解决方案2】:

      问题出在您的主管控制器中。

      
      .then(sup => {
          const resObj = sup.map(supervisor => { // POINT ---- 1
              return Object.assign(
                  {},
                  {
                      id_supervisor : supervisor.id_supervisor,
                      username: supervisor.username,
                      email: supervisor.email,
                      technician: supervisor.tb_tech.map(tec => {
                          return Object.assign(
                              {},
                              {
                                  tech_id : tec.id_tech,
                                  id_user: Usuario.findOne({ // POINT --------- 2
                                      where:{
                                          id_user:tec.id_user
                                      },
                                      attributes:['username']
                                  }).then(user => res.json(user) // POINT 4).catch(error => console.log(error)),
                                  id_supervisor: tec.id_supervisor,
                                  zone: tec.zone,
                                  region: tec.region,
                                  full_name: tec.full_name,
                                  tech_type:tec.tech_type,
                                  goal: tec.goal,
                                  observations: tec.observations,
                                  client: tec.client
                              }
                          )
                      })
                  }
              )
          })
          res.status(200).json(resObj);  // POINT  ------ 3
      })
                    
      

      要点 2:您的 Usuario.findOne 是数据库查询,它是异步的,这意味着它需要时间。 因此,您的 POINT 1 sup.map(supervisor => { 将进入异步执行状态,nodejs 将继续在下一行工作。

      所以 POINT 3 将在下一个事件循环中执行。因此,在执行 POINT 3 时,您的 resObj 为 null 并表示对请求的返回响应。 但是在执行 POINT 4 时,您有 return 语句(即另一个 return 语句) No 2 return 不能在 1 个请求中发生。

      检查 nodejs 的异步特性并正确使用 Promise。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-15
        • 1970-01-01
        • 2019-10-20
        • 1970-01-01
        • 2020-07-11
        相关资源
        最近更新 更多