Node.js express框架/viewRecords子路由间歇性访问超时问题求助
问题根因
- 数据库实例重复初始化冲突:你在
server.js和viewRecordsRoute.js两个文件中,分别对BNE.db、SSC.db两个nedb数据库创建了独立的实例、执行了加载操作。nedb作为文件型数据库,同一时间只允许单个实例持有文件锁,多实例同时访问同一个数据库文件会随机出现锁竞争,导致查询请求被阻塞,这就是故障无规律出现的核心原因。 - 错误分支未返回响应:你在数据库查询的错误分支中,只打印了错误日志就直接return,没有给前端返回任何响应,一旦查询出错(比如锁竞争导致查询失败),请求就会一直挂起,直到浏览器超时。
- 数据库加载未等待完成就挂载路由:
loadDatabase是异步操作,你没有等待数据库加载完成就挂载了路由,极端情况下请求进来时数据库还没加载完成,也会导致查询卡住。
解决方案
第一步:复用数据库实例,删除重复初始化逻辑
删掉viewRecordsRoute.js中所有数据库初始化的代码,把server.js中初始化好的db实例通过参数传递给路由模块。
修改server.js中挂载路由的代码:
// 原代码注释 // const viewRecordsRoute = require('./routes/viewRecords'); // app.use('/viewRecords', viewRecordsRoute); // 修改为传递db实例 const viewRecordsRoute = require('./routes/viewRecords')(bneDB, sscDB); app.use('/viewRecords', viewRecordsRoute);
修改viewRecordsRoute.js代码,接收传入的db实例:
const express = require('express'); const router = express.Router(); // 导出改为工厂函数,接收外部传入的db实例 module.exports = (bneDB, sscDB) => { router.get('/', (request, response) => { response.render('viewRecords.ejs'); }); router.get('/:id', (request, response) => { if (request.params.id == "bne") { bneDB.find({}, (err, output) => { if (err) { console.log(err); // 错误分支必须返回响应,避免请求挂起 return response.status(500).send('数据查询失败'); } response.render('siteRecords.ejs', { site: 'Redbank', records: output }); }); } else { sscDB.find({}, (err, output) => { if (err) { console.log(err); return response.status(500).send('数据查询失败'); } response.render('siteRecords.ejs', { site: 'Column', records: output }); }); } }); return router; }
第二步:优化数据库加载逻辑(可选)
如果要避免数据库未加载完成就收到请求,可以在loadDatabase的回调中再启动服务:
// server.js中修改启动逻辑 let dbLoadedCount = 0; const checkDBAllLoaded = () => { if(dbLoadedCount === 2) { app.listen(port, () => console.log(`Server started on port ${port}`)); } } bneDB.loadDatabase((err) => { if(err) console.error('BNE数据库加载失败', err); dbLoadedCount++; checkDBAllLoaded(); }); sscDB.loadDatabase((err) => { if(err) console.error('SSC数据库加载失败', err); dbLoadedCount++; checkDBAllLoaded(); });
内容的提问来源于stack exchange,提问作者toby86
相关产品推荐
相关产品推荐

