使用fs.readFileSync读取完整路径文件致Express服务504错误排查
问题描述
我当前有一个监听5001端口的Express服务器:
const port = 5001 http.createServer(app).listen(port, () => { console.log(`listening on ${port}`) });
服务器中配置了如下路由:
app.use('/preview/:id', routes);
路由的具体实现如下:
const { generatePreview } = require('../preview') router.get('/preview/:id', generatePreview);
在generatePreview方法中,我尝试使用fs.readFileSync读取文件。首先解析了文件的完整路径:
exports.generatePreview = function (req, res) { const filename = `car-wash-2.html`; const fullpath = resolvePath(__dirname, filename) console.log(fullpath); }
控制台输出的路径为:
/Users/blahblah/Desktop/Work/Code/preview-inkto/preview/car-wash-2.html
该路径已确认是正确的。但执行以下代码时服务挂起并返回504错误:
const html_code = fs.readFileSync(fullpath, 'utf8', (err, data) => { if(err) { res.send(`this is the error: ${err}`); console.error(err) return } res.send(data); return data; })
我无法理解原因:路径正确时服务挂起,而路径错误时却能正常返回路径不存在的错误。请问这是什么问题?
问题解答
问题根源在于你混用了fs模块的同步与异步API:
fs.readFileSync是同步读取方法,它的逻辑是:直接读取文件,成功则返回内容,失败则抛出异常,完全不支持传入回调函数。- 路径正确时,
readFileSync成功读取文件并返回内容,但你没有用这个返回值调用res.send,反而等着一个永远不会被执行的回调来响应请求,导致请求一直挂起,最终超时触发504错误。 - 路径错误时,
readFileSync会直接抛出异常,Express的错误处理机制会捕获这个异常并返回错误响应,所以你能看到路径不存在的提示。
两种修复方式
方式1:正确使用同步API
适合小文件场景,注意同步操作会阻塞Node.js事件循环,高并发场景不推荐:
exports.generatePreview = function (req, res) { const filename = `car-wash-2.html`; const fullpath = resolvePath(__dirname, filename); try { const html_code = fs.readFileSync(fullpath, 'utf8'); res.send(html_code); } catch (err) { res.send(`this is the error: ${err}`); console.error(err); } }
方式2:改用异步API(推荐)
使用fs.readFile异步读取,不会阻塞事件循环,更符合Node.js异步编程模型:
exports.generatePreview = function (req, res) { const filename = `car-wash-2.html`; const fullpath = resolvePath(__dirname, filename); fs.readFile(fullpath, 'utf8', (err, data) => { if(err) { res.send(`this is the error: ${err}`); console.error(err); return; } res.send(data); }); }
内容的提问来源于stack exchange,提问作者FabricioG
相关产品推荐
相关产品推荐

