Node.js使用fs、http模块时响应为何未携带HTML文件数据
问题原因
- 你使用的
fs.readFile是异步非阻塞API,调用后不会立刻返回文件内容,而是会把读取文件的任务交给底层IO线程,自身立刻返回undefined,所以外层赋值的fileContent永远是空值 - 代码中的
res.write、res.end执行时机远早于文件读取完成的回调,等回调里拿到data的时候,响应已经发送结束,自然不会携带HTML内容 - 回调内的
return data没有任何作用,这个返回值只会传递给回调的调用方,不会赋值给外层的fileContent变量,你在回调内能打印出有效data是正常的,但此时已经没法再修改已经发出去的响应了。
修复方案1(回调写法,兼容性最高)
把响应发送的逻辑全部放到fs.readFile的回调函数内,确保拿到文件内容后再返回响应:
const http = require('http'); const fs = require('fs'); const url = require('url'); const meuServ = http.createServer(function (req, res){ const reqUrl = url.parse(req.url, true); const reqUrlPath = reqUrl.path; let fileRes; let statusRes = 200; if(reqUrlPath === '/') { fileRes = 'index.html'; } else if(reqUrlPath === '/summer') { fileRes = 'summer.html'; } else if(reqUrlPath === '/winter') { fileRes = 'winter.html'; } else { statusRes = 404; fileRes = 'notFound.html' }; // 响应逻辑全部放到读取回调内 fs.readFile(fileRes, function (err, data) { if(err) { console.error(err); res.writeHead(500, {'Content-Type': 'text/html'}); res.end('服务器内部错误'); return; } res.writeHead(statusRes, {'Content-Type': 'text/html'}); res.write(data); res.end(); }); }); meuServ.listen(5000, function(){ console.log('servindo'); });
修复方案2(同步读取写法,仅适合练习场景)
把异步的fs.readFile替换为同步APIfs.readFileSync,会阻塞等待文件读取完成后再返回内容,逻辑更直观但生产环境不推荐,会阻塞所有请求的处理:
// 其他逻辑不变,仅修改文件读取和响应部分 try { const fileContent = fs.readFileSync(fileRes); res.writeHead(statusRes, {'Content-Type': 'text/html'}); res.write(fileContent); res.end(); } catch (err) { console.error(err); res.writeHead(500, {'Content-Type': 'text/html'}); res.end('服务器内部错误'); }
内容的提问来源于stack exchange,提问作者Jorge Barbi
相关产品推荐
相关产品推荐

