【问题标题】:Unhandled rejection Error: Can't set headers after they are sent using Node未处理的拒绝错误:使用 Node 发送标头后无法设置标头
【发布时间】:2017-05-18 16:30:26
【问题描述】:

我正在尝试使用 JS、Node 和 Express 呈现视图,但收到此错误“未处理的拒绝错误:发送后无法设置标头”。我知道这与异步回调有关,但是 我不知道如何解决它。

我们认为问题似乎不在于 res.redirect(删除它不会显示数据),而是res.rendervar spaces 没有正确加载到 EJS。当我们输入spaces 时,我们得到消息“object Promise”。

const userController = require('../controllers').user;
const spaceController = require('../controllers').space;

module.exports = (app) => {
  app.get('/', function(req, res) {
      res.render('index.ejs');
  });

  app.post('/users/new', function(req,res){
    userController.create(req,res);
    res.redirect('/');
  });

  app.get('/spaces', function(req, res) {
    var spaces = spaceController.retrieve(req,res);
    res.render('spaces/index.ejs', {spaces});

  });

  app.get('/spaces/new', function(req, res) {
    res.render('spaces/new.ejs');
  });

  app.post('/spaces/new', function(req,res){
    spaceController.create(req,res);
    res.redirect('/spaces');
  });

};

还有我的控制器:

const Space = require('../models').Space;

module.exports = {
  create(req, res) {
    return Space
    .create({
      name: req.body.name,
      description: req.body.description,
      price: req.body.price,
    })
    .then(space => res.status(201).send(space))
    .catch(error => res.status(400).send(error));
  },

  retrieve(req, res) {
    return Space
    .findAll()
    .then(space => {
      if (!space) {
        return res.status(404).send({
          message: 'Space Not Found',
        });
      }
      return res.status(200).send(space);
    })
    .catch(error => res.status(400).send(error));
  },
};

我的看法:

<!doctype html>
 <html>
 <head>
     <title>MakersBnB</title>
     <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
     <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
     <style>
         body        { padding-top:80px; }
     </style>
 </head>
 <body>
 <div class="container">

 <div class="col-sm-6 col-sm-offset-3">
   <div class="jumbotron text-center">

     <h1>Book a Space</h1>

<form action="/spaces/new" method="get">
  <button type="submit" class="btn btn-warning btn-lg">List a space</button>

</form>

<div class="spaces">
  <% spaces.each(function(space) { %>
        <ul>
          <li><%= space.name %></a></li>
          <li><%= space.description %></li>
          <li>£ <%= space.price %></li>
        </ul>
        <% });%>
</div>


 </div>

 </div>
 </body>
 </html>

【问题讨论】:

  • 问题是你的控制器响应了请求,路由器也响应了。例如 app.get('/spaces'

标签: javascript node.js express


【解决方案1】:

您收到此错误是因为您为某些请求发送了多个响应。一个请求只能发送一个响应。

例如在您的/users/new 路由中,您首先调用userController.createuserController.create 发送响应作为函数主体的一部分。

然后您的代码返回到您的/users/new 路由的回调并调用res.redirect('/'),它调用您的/ 路由,该路由也返回一个响应。

要修复,让您的控制器处理发送响应。

例如:

app.post('/users/new', userController.create);

在控制器函数体中,还可以选择渲染哪个视图

app.get('/spaces', spaceController.retrieve);

在控制器中:

 retrieve(req, res) {
    return Space
    .findAll()
    .then(spaces => {
      if (!spaces) {
        return res.status(404).send({
          message: 'Space Not Found',
        });
      }
      return res.status(200).render('spaces/index.ejs', {spaces});
    })
    .catch(error => res.status(400).send(error));
  },

【讨论】:

    【解决方案2】:

    这些路线

     app.post('/users/new', function(req,res){
        userController.create(req,res);
        res.redirect('/');
      });
    
      app.get('/spaces', function(req, res) {
        var spaces = spaceController.retrieve(req,res);
        res.render('spaces/index.ejs', {spaces});
    
      })
     app.post('/spaces/new', function(req,res){
        spaceController.create(req,res);
        res.redirect('/spaces');
      });
    

    spaceController 内部的逻辑已经异步处理对客户端的响应(成功和失败)

    但您立即发送同步响应 (res.redirect),这将阻止您稍后发送异步响应。这会触发异常。

    从三个路由中删除res.redirect 指令应该可以修复它。

    【讨论】:

    • 没有修复它,不幸的是 - 我们认为问题在于 res.rendervar spaces 没有正确加载到 EJS。当我们输入spaces 时,我们得到消息“object Promise”。
    • 这个异常是不言自明的,当你已经发送一个响应时,你正试图向客户端发送一个响应。也许您的代码中还有其他一些错误,但是要修复异常,重点是在您发回响应时
    【解决方案3】:
    app.post('/users/new', function(req,res){
        userController.create(req,res);
        res.redirect('/');
      });
    

    您基本上是以异步方式启动 Space.create() 并在完成之前以重定向响应。

    你可以试试

    app.post('/users/new', 
            userController.create,
            (res,req) => res.redirect('/')
          );
    

    重定向将永远无法到达,但你可以让 userController.create 像这样返回 next()

    create(req, res, next) {
        return Space
        .create({
          name: req.body.name,
          description: req.body.description,
          price: req.body.price,
        })
        .then((space) => {      
          res.locals.space = space || {};
          return next();
        })
        .catch(error => next(error));
      }
    

    使用这个中间件

    app.post('/users/new', 
            userController.create,
            (res,req) => res.status(200).send(res.locals.space)
          );
    

    近期项目的示例: https://github.com/JellyKid/ballsavr/tree/master/Backend/lib

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-02
      • 2023-04-04
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-12
      • 2017-12-20
      相关资源
      最近更新 更多