res.json发送后无法设置标题

我正在学习节点Js,我正在尝试做一个简单的订阅/日志应用程序。 我有问题与res.json不按预期工作。

当我尝试订阅时出现此错误: 发送后无法设置标题

这是我的服务器端脚本:

var express = require('express'); var swig = require('swig'); var ent = require('ent'); var bodyParser = require('body-parser'); var mongoose = require('mongoose'); var session = require('express-session'); var app = express(); // Environnement app.set('port', process.env.PORT || 3000); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use("/public", express.static(__dirname + "/public")); app.engine('html', swig.renderFile); app.set('view engine', 'html'); app.set('views', __dirname + '/views'); app.set('view cache', false); swig.setDefaults({ cache: false }); app.use(session({ secret: 'poussixthetruefighteroftheparadise', saveUninitialized: true, resave: true })); //MongoDB var db = mongoose.connect('mongodb://127.0.0.1:27017/maBase'); var userSchema = new mongoose.Schema({ login: String, mail: String, password: String }); var user = db.model('user', userSchema) // variables globales var state; // Page Principale app.get('/', function(req,res){ if (req.session.user) { res.render('accueil.html',{}); } else { res.redirect('/connection'); } }); // Page connection app.route('/connection') .get(function(req, res) { res.render('index.html',{}); if (req.session.state) { res.json({state: req.session.state}); } }) .post(function(req, res) { user.find({login: req.body.login, password: req.body.password}).limit(1).exec(function (err, users) { if (err) { console.log(err) }; if (!users.length) { console.log('connection pas ok'); res.json({state: '5'}); } else { console.log('connection ok'); res.redirect('/'); } }); }); // Ajouter Utilisateur app.post('/connection/ajouter', function(req,res){ var login = req.body.login; var mail = req.body.mail; user.find({$or: [{login: login}, {mail: mail}]}).limit(1).exec(function (err, users) { if (err) { console.log(err) }; if (!users.length) { console.log('login et mail ok'); if (req.body.password == req.body.password2) { if (req.body.password.length > 6) { var values = new user({ login: ent.encode(req.body.login), mail: ent.encode(req.body.mail), password: ent.encode(req.body.password) }); values.save(function(err, values) { if (err) return console.error(err); console.log('utilisateur enregistré'); req.session.state = '6'; res.redirect('/connection'); }); } else { console.log('Mot de passe trop court'); req.session.state = '3'; res.redirect('/connection'); } } else { console.log('mot de passe différent'); req.session.state = '4'; res.redirect('/connection'); } } else { console.log('login ou mail déja utilisé'); if (users[0].mail == mail) { console.log('mail déja utilisé'); req.session.state = '2'; res.redirect('/connection'); } else { console.log('login déja utilisé'); req.session.state = '1'; res.redirect('/connection'); } console.log(users); } }); }); app.listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); }); 

而我的客户端脚本:

 <html> <head> <title>test</title> <link rel="stylesheet" href="public/css/reset.css"> <link rel="stylesheet" href="public/css/connection.css"> </head> <body> <div id="content"> <a href="http://localhost:3000"><img src="public/images/icone.jpg" alt="gatsbill"></a> <div id="wrap"> <div id="espacehaut"></div> <div class="click" id="con" style="display: block;">Se connecter</div> <div class="click" id="sub" style="display: none;">S'inscrire</div> <div id="connection" style="display: none;"> <div id="message1" class="message" style="display: none;"></div> <form action="/connection/" method="post" id="form_connection"> <input type="text" name="login" id="login" placeholder="Login" value="" required="" autofocus=""> <input type="password" name="password" id="password" placeholder="Password" required=""> <input type="submit" name="submit" value="Connect"> </form> </div> <div id="subscribe" style=""> <p id="p">Pour vous inscrire,<br> Veuillez remplir les champs ci-dessous</p> <div id="message2" class="message" style="display: none;"></div> <form action="/connection/ajouter/" method="post" id="form_inscription"> <input type="text" name="login" placeholder="Login" value="" required="" autofocus=""> <input type="email" name="mail" placeholder="Email" value="" required=""> <input type="password" name="password" placeholder="Password" required=""> <input type="password" name="password2" placeholder="Password" required=""> <input type="submit" name="submit" value="Create account"> </form> </div> <div id="espacebas"></div> </div> </div> <!-- Script --> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script type="text/javascript" src="public/js/connection.js"></script> <script> $.getJSON( "http://localhost:3000/connection", function(data){ if( data.state ) { state = parseInt(data.state); switch (state) { case 1: formulaire(); $("#message2").text("login déja utilisé"); break; case 2: formulaire(); $("#message2").text("mail déja utilisé"); break; case 3: formulaire(); $("#message2").text("Mot de passe trop court"); break; case 4: formulaire(); $("#message2").text("mot de passe différent"); break; case 5: connect(); $("#message1").text("connection pas ok"); break; case 6: connect(); $("#message1").text("vous pouvez maintenant vous connecter"); break; } } }); </script> </body> </html> 

当我试图订阅两个不同的密码这是我有:

只有这样的白页:

{ “状态”: “4”}

当然这个错误在节点Js控制台: 发送后无法设置标头

欢迎来到nodejs / express!

这是您在控制台中获取“发送后无法设置标头”错误的位置:

 // Page connection app.route('/connection') .get(function(req, res) { res.render('index.html',{}); if (req.session.state) { res.json({state: req.session.state}); } }) 

在这个configuration中, res.renderres.json都会调用res.end() ,这基本上就像试图向客户端发送一个响应两次。

您应该在res.render之前放置一个return语句,或者将{state: req.session.state}res.render()调用的第二个参数,然后使用swig模板来显示该数据。

我已经这样解决了:

在第一个中间件中覆盖res.send:

 app.use(function(req,res,next){ var _send = res.send; var sent = false; res.send = function(data){ if(sent) return; _send.bind(res)(data); sent = true; }; next(); });