NodeJS执行SELECT @@SERVERNAME获取SQL主机名并传递至EJS的实现方案
核心问题修正方案
1. 正确提取SELECT @@SERVERNAME的返回值
当前用字符串硬替换recordset序列化结果的方式鲁棒性极差,只要主机名包含"、}这类特殊字符就会提取失败。
按照mssql库的返回结构,无表头的查询结果,列名默认是空字符串'',因此可以直接从数组索引取值,无需做字符串切割:
- 查询成功后
rec.recordset是长度为1的对象数组,对应查询返回的单行结果 - 该行对象的空键
''存储的就是SQL Server主机名字段值
正确提取代码片段:
request.query('select @@SERVERNAME', (err, rec) => { if (err) { console.error('查询SQL Server主机名失败:', err) return } // 直接结构化取值,替换原有的字符串replace逻辑 const sqlServerHostname = rec.recordset[0][''] console.log('SQL Server运行节点:', sqlServerHostname) })
2. 变量存储与EJS传值实现
当前的核心实现痛点是异步回调的作用域时序问题:SQL查询是异步执行的,如果直接在代码顶层定义变量赋值,很容易在变量还没被异步回调赋值时,就被Express路由读取到undefined值。
推荐实现逻辑
- 在模块顶层定义全局存储对象,分别存两类节点信息:
- Node.js运行节点主机名:直接用
os.hostname()同步获取,无异步延迟 - SQL Server运行节点主机名:等数据库连接、主机名查询完成后赋值
- Node.js运行节点主机名:直接用
- 等待所有节点信息获取完成后,再启动Express服务,从根源上避免时序问题
- 在页面路由中把存储的两类节点信息作为render参数传给EJS模板
完整可运行的修正代码:
const express = require('express') const os = require('os') const mssql = require('mssql') const dbconfig = require('./src/config/dbconfig.json') // 初始化站点展示所需的全局数据 const appData = { nodeHostname: os.hostname(), sqlServerHostname: '' } const app = express() // 配置EJS模板引擎 app.set('view engine', 'ejs') // 首页路由 app.get('/', (req, res) => { res.render('index', { nodeHost: appData.nodeHostname, sqlHost: appData.sqlServerHostname }) }) const pool = new mssql.ConnectionPool(dbconfig) // 建立数据库连接 pool.connect((err) => { if (err) { console.log('数据库连接失败:', err) process.exit(1) } const request = new mssql.Request(pool) request.query('select @@SERVERNAME', (queryErr, rec) => { if (queryErr) { console.error('SQL Server主机名查询失败:', queryErr) appData.sqlServerHostname = '信息获取失败' } else { // 结构化提取主机名 appData.sqlServerHostname = rec.recordset[0][''] console.log(`已获取SQL Server节点信息: ${appData.sqlServerHostname}`) } // 等所有节点信息就绪后再启动服务 app.listen(3000, () => { console.log('演示站点已启动,访问地址: http://localhost:3000') }) }) })
EJS模板展示逻辑
在views/index.ejs文件中直接引用路由传递的变量即可:
<div class="node-info"> <h3>架构演示:节点部署信息</h3> <p>Node.js应用运行节点: <%= nodeHost %></p> <p>SQL Server数据库运行节点: <%= sqlHost %></p> </div>
关键注意事项
- 不要依赖JSON字符串替换提取数据库返回值,结构化索引取值的可靠性远高于字符串切割,不会受主机名特殊字符影响
- 不要在异步操作未完成前启动Express服务,否则页面首次加载时会拿到未初始化的空值,不符合K8s演示的展示要求
- 该方案获取的SQL Server主机名是数据库实例自身的标识,和Node.js本机的主机名完全独立,可以准确区分两个运行节点的信息
内容的提问来源于stack exchange,提问作者Steven com my
相关产品推荐
相关产品推荐

