Express+SQLite3首次请求无数据需刷新,如何解决?
问题描述
使用Express框架搭配SQLite及SQLite3模块开发时,启动服务器后首次请求无法加载数据,必须刷新页面才能显示。尝试将db.each()包装为Promise并等待执行完成后渲染页面,但未生效,且仅使用SQLite3,不考虑SQLite3-express。
错误原因分析
db.each()异步处理逻辑错误:db.each()是异步方法,当前代码在调用后立即resolve(rows),此时遍历还未完成,首次请求时rows只有初始值;刷新时因全局rows已缓存之前的数据,所以能显示。- 全局变量
rows导致数据污染:rows定义在全局作用域,每次查询都会追加数据,多次请求后数据重复。 - 重复创建数据库连接:每次调用
query都新建连接,既低效又可能引发连接泄漏。 getMultiple()无返回值:该函数使用await但未返回结果,导致路由中res.json()接收的是undefined。
修正后的代码
db.js
const sqlite3 = require('sqlite3').verbose(); const path = "C:/Users/Administrateur.DESKTOP-OQRUHSR/Desktop/sqlite-tools-win32-x86-3410000/db/test.db"; // 全局创建一次数据库连接,避免重复初始化 const db = new sqlite3.Database(path, (err) => { if (err) { console.error("数据库连接失败:", err.message); } else { console.log("数据库连接成功"); } }); function query(sql) { return new Promise((resolve, reject) => { const rows = []; db.each(sql, (err, row) => { if (err) { console.error(err.message); reject(err); // 捕获行处理错误并reject return; } rows.push(row); console.log(row.id, row.name); }, (err, count) => { // 遍历完成的回调,所有行处理完毕后执行 if (err) { reject(err); } else { console.log(`共查询到${count}条数据`); resolve(rows); } }); }); } module.exports = { query };
prog.js
const db = require('./db'); async function getMultiple() { // 返回查询结果,确保上层能获取到数据 return await db.query("SELECT id, name FROM users"); } module.exports = { getMultiple };
routes.js
const express = require('express'); const router = express.Router(); const programmingLanguages = require('../services/prog'); router.get('/', async function (req, res, next) { try { const data = await programmingLanguages.getMultiple(); res.json(data); } catch (err) { console.error(`获取数据时出错:`, err.message); next(err); } }); module.exports = router;
关键修正说明
- 正确处理
db.each()异步流程:利用db.each()的第三个完成回调,确保所有行遍历完成后再resolvePromise,保证数据完整。 - 移除全局
rows变量:每次查询创建局部数组,避免数据污染。 - 复用数据库连接:全局初始化一次连接,提升性能并避免连接泄漏。
- 完善错误处理:在
db.each()的行处理和完成回调中捕获错误,通过reject抛出,便于上层统一处理。 - 确保函数返回值:
getMultiple()返回查询结果,让路由能正确响应数据。
内容的提问来源于stack exchange,提问作者mazen_sars
相关产品推荐
相关产品推荐

