各位大神晚上好,这个问题是我使用rrestjs时候偶然发现的,网上也没查阅到相关资料,写了如下的issues提交给老吴了,以下是发现这个问题的被坑、寻坑、填坑的过程。
当我实现了旁路业务和核心业务分离之后,随之而来的就遇到一些列的麻烦和问题,程序会莫名其妙的告诉我
Error: Can't set headers after they are sent.
,通过一个案例测试出来,案例如下:
var http = require('http');
var rrest = require('rrestjs');
var server = http.createServer(function(req,res){
if(true){
res.send('123');
}
res.send('321');
}).listen(80);
当我打开浏览器输入
127.0.0.1
的时候,页面是显示123
,但是后台报错
http.js:644
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.js:644:11)
at RestZlib.send (D:\projects\eclipse\node_modules\rrestjs\lib\RestZlib.js:20:7)
at Gzip.onEnd (zlib.js:153:5)
at Gzip.EventEmitter.emit (events.js:85:17)
at zlib.js:349:10
at Zlib.callback (zlib.js:439:13)
这样的错误我在原生的写法里没有遇到过,于是我开始用原生写法如下案例测试
var http = require('http');
var server = http.createServer(function(req,res){
if(true){
res.write(JSON.stringify({a:123}));
res.end();
}
res.write(JSON.stringify({a:321}));
res.end();
}).listen(80);
浏览器显示
{"a":123}
好的,这没报错,这不是我所希望的,我反而希望他报错,于是我看了下之前的报错提示Can't set headers after they are sent.
,翻译过来就是他们已经发送,您无法设置headers
,难道发送后就不能设置headers了吗?于是我改进了原生代码,是这样的
var http = require('http');
var server = http.createServer(function(req,res){
if(true){
res.writeHeader(200, {'Content-Type':'text/javascript;charset=UTF-8'})
res.write(JSON.stringify({a:123}));
res.end();
}
res.writeHeader(200, {'Content-Type':'text/javascript;charset=UTF-8'})
res.write(JSON.stringify({a:321}));
res.end();
}).listen(80);
结果是浏览器依然有显示后台也没报错,我很不甘心,于是我想,是不是要在发送后,设置点不一样的headers呢?继续改进原生的代码
var http = require('http');
var server = http.createServer(function(req,res){
if(true){
res.writeHeader(200, {'Content-Type':'text/javascript;charset=UTF-8'})
res.write(JSON.stringify({a:123}));
res.end();
}
res.writeHead(200, {'Content-Length': 1024,'Content-Type': 'text/plain;charset=GBK' });
res.write(JSON.stringify({a:321}));
res.end();
}).listen(80);
node似乎很智能啊,这样依然没有报错,我依然不甘心,我把关键字锁定在了
set
上,我想我是不是该调用setHeader方法呢,于是我这样
var http = require('http');
var server = http.createServer(function(req,res){
if(true){
res.setHeader('Content-Type','text/javascript;charset=UTF-8');
res.write(JSON.stringify({a:123}));
res.end();
}
res.setHeader('Content-Length',1024);
res.setHeader('Content-Type','text/html;charset=GBK');
res.write(JSON.stringify({a:321}));
res.end();
}).listen(80);
好吧,其实我已经精疲力尽的写到这了,我真希望这个错误能重现,果然出现了,和rrestjs框架所报的错误一模一样,因此呢…… 我的建议就是将setHeader都替换为writeHeader,这样他不会报错,而且一旦发送出去req是不会重发(后面的依然会执行,但不会重发)。 另外我想知道setHeader和writeHead的本质区别
问题是已经发给老吴了,也发给大家看看,希望大家帮忙找找相关文案,迫切想知道这2个方法的本质区别(包括为什么writeHead重复设置不会报错,而setHeader会报错),小弟拜谢!