刚开始接触NodeJs便多次听到它是 单线程异步非阻塞IO模型 ,虽然看过好多例子,然而还是不怎么理解,借着一个BUG整理下思路。
问题
- 尝试给一个本地的项目做一个简单的服务器时,用了如下的语句
实际上用不着这么麻烦,这是我自己想到的处理方法
var backHeader = {
'html' : {
'content-type' : 'text/html',
'charset':'utf8'
},
'css' : {
'content-type' : 'text/css',
'charset':'utf8'
},
'pic' : {
'content-type' : 'image/jpeg',
'charset':'utf8'
},
'js' : {
'content-type' : 'application/x-javascript',
'charset':'utf8'
}
}
......
//对应不同的请求后缀名,给予不同的响应报文头
var staticHead = "";
if(url.endsWith('.jpg') || url.endsWith('.jpeg'))
staticHead = backHeader['pic'];
else if( url.endsWith('.css') ){
staticHead = backHeader['css'];
}
else if(url.endsWith('.js')){
staticHead = backHeader['js'];
}
else if(url.endsWith('.html')){
staticHead = backHeader['html'];
}
//读取请求的文件,并写入对应的报文头
fs.readFile(file,function(err,data){
if(err){
......
}
else{
console.log(staticHead); //调试时加入的代码
res.writeHeader(200,staticHead);
res.write(data);
res.end();
}
});
- 但实际查看时,却发现有某些css文件的报文头出错:
出错的报文头
原因
-
尝试在控制台输出了每一次的响应报文头,发现输出是这样的:
分析这段代码的工作方式:
- 分析传入的URL,并将对应的响应报文头存储到变量staticHead中
- 读取URL请求的文件
- 文件读取完毕后输出对应的响应报文头(调试代码)
- 将读出来的文件内容写入到响应报文体中
- 将响应报文发给浏览器来解析
虽然每个文件的响应报文头是没问题的,但存储响应报文头的变量staticHead只有一个, 这就是问题的所在:
- 当接收到
/css/menu.css
的请求时,分析了URL并得出了正确的结果存储在staticHead 中 - 开始读取menu.css文件
- 接收到请求
/js/menu_js.js
,开始分析URL,将结果存储在staticHead中,此时menu.css文件还没有读取出来,但它的响应报文头已经被覆盖为了js文件的响应报文头 - menu.css 文件读取成功,写入staticHead到响应报文,写入读取的数据到响应报文
- 将响应报文发送给浏览器
- 浏览器接收到menu.css文件的内容,并根据响应报文头将它解析为js文件
解决
- 将分析URL的判断部分放到 fs.readFile(file,callback) 的回调函数部分中去
- 利用NodeJs事件驱动的特性,只有当某个文件读取完成后,才会分析该文件的文件类型,写入到响应报文中发送给浏览器端,这个过程中,不会有其他对staticHead的操作,解决了问题
网友评论