Express:发送后无法设置标题

以下是我的服务器文件。 我打了两个电话,一个邮件,一个得到。 它有时工作正常。 但给出错误:发送后无法设置标题。 这与我的客户端代码有什么关系吗?

server.js

var express = require('express') var mongoose = require('mongoose') var path = require('path') var bodyParser = require("body-parser") var cors = require("cors") var app = express() var port = process.env.PORT || 3000 var Url = require("./data/url-schema"); //Express request pipeline app.use(express.static(path.join(__dirname,"../client"))) app.use(bodyParser.json()) app.use(cors()); /* Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response. */ app.get('*', function (request, response, next){ response.sendFile(path.resolve(__dirname, '../client', 'index.html')) next() }) app.get('/:code', function(req, res) { console.log("reg", req.params.code) Url.findOne({code:req.params.code}, function(err, data){ console.log("data", data) if(data) res.redirect(302, data.longUrl) else res.end() }) }) app.post('/addUrl', function (req, res, next) { console.log("on create"); Url.findOne({longUrl:req.body.longUrl}, function(err, data) { if (err) res.send(err); else if(data) { console.log("already exists",data) res.send("http://localhost:3000/"+data.code); } else { var url = new Url({ code : Utility.randomString(6,"abcdefghijklm"), longUrl : req.body.longUrl }); console.log("in last else data created",url) url.save(function (err, data) { console.log(data) if (err) res.send(err); else res.send("http://localhost:3000/"+data.code); }); } }); }) app.listen(port, function () { console.log('Example app listening on port 3000!') }); // Connect to our mongo database mongoose.connect('mongodb://localhost/shortUrl'); 

我得到以下错误

错误

 _http_outgoing.js:335 throw new Error('Can\'t set headers after they are sent.'); ^ Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11) at ServerResponse.header (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:718:10) at ServerResponse.location (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:835:8) at ServerResponse.redirect (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:874:8) at Query.<anonymous> (/opt/lampp/htdocs/url-shortener/server/server.js:30:8) at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:177:19 at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:109:16 at process._tickCallback (node.js:355:11) 

根据执行顺序,在*路由处理程序中,正文被分配给响应,然后在/:code ,响应代码302被添加,其中Location标题也被添加,因此是错误。 任何标题必须添加到响应正文之前。

要解决这个问题,只需改变两个GET语句的顺序。

终于find了解决办法:

 var express = require('express') var mongoose = require('mongoose') var path = require('path') var bodyParser = require("body-parser") var app = express() var port = process.env.PORT || 3000 var Url = require("./data/url-schema") var Utility = require("./utility") //Express request pipeline app.use(express.static(path.join(__dirname,"../client"))) app.use(bodyParser.json()) /* Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response. */ app.get('/dashboard', function (request, response, next){ response.sendFile(path.resolve(__dirname, '../client', 'index.html')) next() }) app.get('/about', function (request, response, next){ response.sendFile(path.resolve(__dirname, '../client', 'index.html')) next() }) app.get('/:code', function(req, res) { Url.findOne({code:req.params.code}, function(err, data){ if(data){ res.redirect(302, data.longUrl) } }) }) app.post('/addUrl', function (req, res, next) { Url.findOne({longUrl:req.body.longUrl}, function(err, data) { if (err){ res.send(err) } else if(data) { res.send("http://localhost:3000/"+data.code); } else { var newCode = getCode() checkCode(newCode) .then(function(data){ var url = new Url({ code : data, longUrl : req.body.longUrl }); url.save(function (err, data) { if (err) res.send(err); else res.send("http://localhost:3000/"+data.code); }); }) } }); }) app.listen(port, function () { console.log('Example app listening on port 3000!') }); // Connect to our mongo database mongoose.connect('mongodb://localhost/shortUrl'); //Generate a random code function getCode() { return Utility.randomString(6,"abcdefghijklmnopqrstuvwxyz") } //Check if the code is unique function checkCode(code) { return new Promise(function (resolve, reject){ Url.findOne({code:code}, function(err, data) { if(err === null){ resolve(code) }else if(data){ saveUrlCode(getCode()) } }) }) } 

我之前的路线是:

 app.get('*', function (request, response, next){ response.sendFile(path.resolve(__dirname, '../client', 'index.html')) next() }) 

由于上述调用和app.get(“:/ code”)调用,得到的路由被执行了两次。 所以我不得不通过处理仪表板和关于路线而不是使用“*”路线来正确处理路线。