未处理拒绝错误:使用Node发送标头后无法设置标头

时间:2017-05-18 16:30:26

标签: javascript node.js express

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

问题似乎与res.redirect无关(删除它不显示数据),而是/usr/binres.render没有正确加载到EJS,我们认为。当我们放置var spaces时,我们会收到消息“object Promise”。

spaces

我的控制员:

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));
  },
};

3 个答案:

答案 0 :(得分: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));
  },

答案 1 :(得分:0)

这些路线

 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指令应该修复它。

答案 2 :(得分:0)

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