nodejs错误:将标头发送到客户端后无法设置标头

时间:2019-05-07 07:57:53

标签: node.js

我正在使用HTML和nodejs创建一个简单的表单。表单接受电子邮件和密码这两个数据,并根据代码中编写的功能工作。

我的程序中有两个文件app.jsindex.html

  

app.js

const _ = require('lodash');
const express = require('express');
const path = require('path');
const Joi = require('joi');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

app.get('/',(req,res)=>{

    res.sendFile(path.join(__dirname,'index.html'));

});

app.get('/example',(req,res)=>{

    res.send('Hitting Example Route');

});

app.get('/example/:name/:age',(req,res)=>{

    console.log(req.params);
    console.log(req.query);
    //res.send('example with route params');
    res.send(req.params.name+":"+req.params.age);

});

app.post('/',(req,res)=> {
    console.log(req.body);
    const schema = Joi.object().keys({

        email : Joi.string().trim().email().required(),
        password : Joi.string().min(5).max(10).required()
    });

    Joi.validate(req.body,schema,(err,result)=>{
        if(err)
        {
            console.log(err);
            res.send('An error has occured');
        }
        console.log(result);
        res.send('Successfully posted data');

    });
    //database work here

    //res.json({success:true});

});

app.listen(3000);
  

index.html

<!DOCTYPE html>
<html>

   <head>
      <title>Text Input Control</title>
   </head>

   <body>
      <!--<form !action="/"></form> method="POST" id="form">-->
      <form  method="POST" id="form">

         First name: <input type = "text" name = "first_name" />
         <br>
         Last name: <input type = "text" name = "last_name" />

         <input type="submit" value="Submit">

      </form>

            <script
        src="http://code.jquery.com/jquery-3.3.1.js"
        integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
        crossorigin="anonymous"></script>

        <script>
            $(document).ready(()=>{
                $('#form').submit((e)=>{
                    e.preventDefault({});
                    $.ajax({

                        url : '/',
                        type : 'post',
                        contentType : 'application/json',
                        data : JSON.stringify($('#form').serializeArray()),
                        success : (response)=>{

                            console.log('Successfuly got response');
                            console.log(response);

                        }

                    });

                });


            });

        </script>

   </body>

</html>

我收到一条错误消息,指出Cannot set headers after they are sent to the client。我该如何修复代码?

  

错误:

PS F:\DatabaseProject8> node app.js
[ { name: 'first_name', value: 'hello@gmail.com' },
  { name: 'last_name', value: 'gredyjht' } ]
{ ValidationError: "value" must be an object
    at Object.exports.process (F:\DatabaseProject8\node_modules\joi\lib\errors.js:203:19)
    at internals.Object._validateWithOptions (F:\DatabaseProject8\node_modules\joi\lib\types\any\index.js:764:31)
    at module.exports.internals.Any.root.validate (F:\DatabaseProject8\node_modules\joi\lib\index.js:147:23)
    at app.post (F:\DatabaseProject8\app.js:40:9)
    at Layer.handle [as handle_request] (F:\DatabaseProject8\node_modules\express\lib\router\layer.js:95:5)
    at next (F:\DatabaseProject8\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (F:\DatabaseProject8\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (F:\DatabaseProject8\node_modules\express\lib\router\layer.js:95:5)
    at F:\DatabaseProject8\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (F:\DatabaseProject8\node_modules\express\lib\router\index.js:335:12)
  isJoi: true,
  name: 'ValidationError',
  details:
   [ { message: '"value" must be an object',
       path: [],
       type: 'object.base',
       context: [Object] } ],
  _object:
   [ { name: 'first_name', value: 'hello@gmail.com' },
     { name: 'last_name', value: 'gredyjht' } ],
  annotate: [Function] }
[ { name: 'first_name', value: 'hello@gmail.com' },
  { name: 'last_name', value: 'gredyjht' } ]
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:470:11)
    at ServerResponse.header (F:\DatabaseProject8\node_modules\express\lib\response.js:767:10)
    at ServerResponse.send (F:\DatabaseProject8\node_modules\express\lib\response.js:170:12)
    at Joi.validate (F:\DatabaseProject8\app.js:47:13)
    at internals.Object._validateWithOptions (F:\DatabaseProject8\node_modules\joi\lib\types\any\index.js:767:20)
    at module.exports.internals.Any.root.validate (F:\DatabaseProject8\node_modules\joi\lib\index.js:147:23)
    at app.post (F:\DatabaseProject8\app.js:40:9)
    at Layer.handle [as handle_request] (F:\DatabaseProject8\node_modules\express\lib\router\layer.js:95:5)
    at next (F:\DatabaseProject8\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (F:\DatabaseProject8\node_modules\express\lib\router\route.js:112:3)

4 个答案:

答案 0 :(得分:2)

在两次设置标头时都会出错,原因是Joi.validate回调中发生错误。您正在发送“发生了错误”,但是在错误处理程序之后,您仍在发送“成功发布数据”。您不应两次致电send,否则会收到该错误。发生错误时,您应该退出Joi.validate回调。

答案 1 :(得分:1)

您定义的架构可能不正确

像这样定义它

const schema = {
    email: Joi.string().trim().email().required(),
    password: Joi.string().min(5).max(10).required()
};

答案 2 :(得分:0)

有时候我遇到这个问题,我解决了res.send的变更问题res.redirect('/example')

您可以尝试的另一件事是更改if语句,是否可能在发生两次错误res.send的情况下:

if(err){
            console.log(err);
            res.send('An error has occured');
        } 
else {
        console.log(result);
        res.send('Successfully posted data'); 
}

答案 3 :(得分:0)

您得到的错误是由于Nodejs的异步特性。使用Promise / Async-Await来防止此类错误。 使用Async-Await

app.post('/',async(req,res)=> {
console.log(req.body);
const schema = Joi.object().keys({

    email : Joi.string().trim().email().required(),
    password : Joi.string().min(5).max(10).required()
});

let result = await Joi.validate(req.body,schema);
if(result.err){
    console.log(err);
    res.send('An error has occured');
}else{
    console.log(result);
    res.send('Successfully posted data');
}
//database work here

//res.json({success:true});

});

这可以完成工作