我正在使用HTML和nodejs创建一个简单的表单。表单接受电子邮件和密码这两个数据,并根据代码中编写的功能工作。
我的程序中有两个文件app.js
和index.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)
答案 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});
});
这可以完成工作