关于Error: Can't set headers after they are sent.
发布于 7 年前 作者 ZJH9Rondo 3709 次浏览 来自 问答

首先,这个问题查看了Stackoverflow上的所有解释,还是没有找到合适的解决办法,都试了一遍,加断点Debug也找不出来

问题描述:

*	现在注释了路由中除去获取index的路由响应外的所有路由,排除问题出现以下特征
*  第一次打开了浏览器获取页面不会出现报错,但是当在此刷新就会出现题目中的错误,不明白为什么
* 	有一个Ajax请求获取数据,打开浏览器页面点击发送请求,第一次不会出现重复响应,第二次再点击时加断点发现会出现重复响应,它在接收到Ajax请求时,会查询数据库进行正确的操作,但是在一切结束后,它不会返回,而是又进行了一次一一模一样的操作,但是由于之前的操作已经更新了数据库,所以返回的已经不再是期待中的结果,为什么说重复响应?因为请求URL加了随机数,打印发现两次随机数一模一样,排除Ajax重复发送的可能,最奇怪的一点是当我第一次点击之后如果等待五六分钟再点击是正常的,不会重复响应,但是如果立即点击或等待一两分钟操作还是会重复请求

以上所有问题描述的错误均排除

*	1.数据库缓存或数据库更新慢
*	2.AJax重复发送请求
*	3.Ajax从缓存中读取,因为已经禁用了缓存
*   4.以及任何可能的偶然因素

附上此部分代码链接,还望大牛帮忙看看,自己琢磨了两天了,这个BUG还是解决不掉,主要问题可能出在posts.js中

	https://github.com/ZJH9Rondo/Blog-Node/tree/master/routes
12 回复

问题应该描述的清楚了。stackoverflow上一直提到重写响应头的问题,但是在出问题的地方,检查了无数遍代码,没有这个代码上的错误啊

报错的原因是某个地方 res.send之后 没有结束,后面又出现了send或者write之类的? 有堆栈的报错信息吗?

@imhered 我就是怕出现此类问题,在我最后改的时候我直接把其余的路由代码直接注释掉了,就留了获取 index 和 posts 两个页面的路由,这两个里面只存在 res.render() 的操作,报错信息有 这是第一次打开浏览器进入页面的数据信息 untitled1.png

这是第二次刷新就会报错的信息: untitled2.png

响应的路由代码:

		//routes/index.js
	module.exports = function(app){
	
		app.get('/',function(req,res,next){
		   res.render('index');
		});
	
	
	
	};

	router.get('/posts',function (req,res,next){
	// author 区分用户页和主页
	var author = req.query.author;
  
	PostModel.getPosts(author).then(function (result) {
		var posts = result;
  
		if(req.session.user){
		  var authorCollected = req.session.user._id;
  
		  PostModel.getCollections(authorCollected).then(function (result){
			var collections = result.collections;
  
			 res.render('posts', {
				posts: posts,
				collections: collections
			});
		  });
		}else{
			 res.render('posts',{
				posts: posts
			});
		}
  });
});	

@imhered 而且现在这个又不影响正常运行,但是对数据库的访问操作由于这个问题会出现误操作或者重复操作影响

用二级路由试试 app.use(’/sign’,require(’./sign’))

@godghdai 之前用的就是二级路由,但是问题还是出现

这三个中间件顺序交换下,再试试

// session
app.use(session({
    name:config.session.key, // 设置cookie中保存session id的字段名称
    secret:config.session.secret, // 通过设置secret来计算hash值并放在cookie中,使产生的signedCookie防篡改
    resave: true,
    saveUninitialized: true,
    cookie: {
        maxAge:config.session.maxAge // 过期时间,过期后cookie中的session id自动删除
    },
    store:new MongoStore({ // 将session存放到mongodb
        db:config.db,
        url:config.mongodb // mongodb地址
    })
}));
// 路由
routes(app);
// 默认模板目录
app.use(express.static(path.join(__dirname, 'public')));

我clone你的repo重现了你的问题 只要把处理表单的中间件去掉或者把routes(app)放到处理表单的中间件上问题就没有这个错误了 所以可能是express-formidable这个中间件有问题

你遇到的问题,我最近纠结了好久 我教朋友学 node ,让她实现的功能就是在 express 中使用 session+ redis 实现 session 过期自动跳转到登录页,功能很简单,可是她那边一直提示你说的错误,然后我就把我本地的node 版本+ express 版本弄成和她的版本一致,在我本地调试好再发给她,还是一样的问题,然后我放弃了 ps: session那离要放在 路由上面,session里面的 store 注释掉,就不会出现这个问题了,麻烦你找到原因后回复我下,谢谢了

@alphaXkiller 真的是万分感谢,错误解决了,是顺序问题,代码已经更新,具体结果大佬有兴趣可以再去看看具体更改,真的是不知道怎么感谢,错误解决了就好,接下来就是定位具体的错误原因了,看那个中间件出了问题,感谢。

@enternoder 可以把具体代码链接发下吗?看你描述可能是不清楚store的具体作用,你可以先去看以下关于 API 的介绍,再试着更改,这种错误看到代码才能给出准确的解答,就像我这种错误,虽然原因都知道是重写了响应头,但是具体错误出在哪还是要代码重现才能找出来。

@ZJH9Rondo 我本地是正常的,发给她后,她那边就开始报错

回到顶部