Node.js用createPool()连接Oracle报NJS-047错误解决方案咨询
错误原因
- 异步逻辑未等待:
config.init()是异步函数,app.js的路由处理函数没有使用await等待执行结果,导致oracledb.createPool()还没完成创建连接池的操作,后续getConnection()就已经执行,找不到默认连接池抛出NJS-047错误。 - 连接池重复创建:当前逻辑每次请求
/getCustomerName接口都会调用一次init()尝试创建新的连接池,连接池全局只需初始化一次即可,重复创建不仅性能差还会引发状态异常。 - 查询结果未返回:
dostuff函数执行查询后没有将结果return,上层调用即使等待执行完成也拿不到查询数据,所以接口返回空内容。
修复方案
第一步:修改config.js,拆分连接池初始化和查询逻辑
const oracledb = require('oracledb') oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT // 初始化连接池,服务启动时调用一次即可 const initPool = async function () { try { await oracledb.createPool({ user: 'almat', password: 'almat789456123', connectString: '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=xepdb1)))' }) console.log('Connection pool started') } catch (err) { console.error('initPool() error: ' + err.message) throw err // 抛出错误让上层感知初始化失败 } } // 单独封装查询方法,每次请求调用 const executeQuery = async function(query, binds = []) { let connection try { connection = await oracledb.getConnection() const options = { outFormat: oracledb.OUT_FORMAT_OBJECT } const result = await connection.execute(query, binds, options) return result // 返回查询结果 } catch (err) { console.error('executeQuery error:', err) throw err } finally { if (connection) { try { await connection.close() } catch (err) { console.error('connection close error:', err) } } } } async function closePoolAndExit () { console.log('\nTerminating') try { await oracledb.getPool().close(10) console.log('Pool closed') process.exit(0) } catch (err) { console.error(err.message) process.exit(1) } } process .once('SIGTERM', closePoolAndExit) .once('SIGINT', closePoolAndExit) module.exports = { initPool, executeQuery }
第二步:修改app.js,启动时初始化连接池,路由添加异步等待
const express = require('express'); const { initPool, executeQuery } = require('./utils/config'); const app = express(); app.set('view engine', 'ejs') app.get('/', function (req, res) { return res.render('index') }) app.get('/login', function (req, res) { return res.render('login') }) // 路由处理函数加async关键字 app.get('/getCustomerName', async function (req, res) { try { const query = 'SELECT firstname FROM customer WHERE :b = 1' const binds = [1] const result = await executeQuery(query, binds) // 等待查询结果 return res.send(result) } catch (err) { return res.status(500).send({ error: err.message }) } }) // 先初始化连接池,成功后再启动服务 async function startServer() { try { await initPool() app.listen(3000, function () { console.log('Server running at port 3000') }) } catch (err) { console.error('Server start failed:', err) process.exit(1) } } startServer() module.exports = app
修复说明
- 连接池改为服务启动时一次性初始化,避免每次请求重复创建
- 所有异步操作都添加
await等待执行完成,保证时序正确 - 封装独立的查询方法,直接返回查询结果,接口可以正常拿到数据返回给前端
- 添加异常捕获,接口异常时返回明确的错误信息,方便排查
内容的提问来源于stack exchange,提问作者Almat Kaipzhanov
相关产品推荐
相关产品推荐

