Node.js连接Heroku PostgreSQL报错:Cannot read property 'query' of null如何解决?
TypeError: Cannot read property 'query' of null in Node.js + PostgreSQL (Heroku)
我有一个连接Heroku PostgreSQL的Node.js文件,代码如下:
var express = require('express'); var pg = require('pg'); var app = express(); var connectionString = "postgres://..."; app.get('/', function (req, res, next) { pg.connect(connectionString, function (err, client, done) { if (err) { console.log("not able to get connection " + err); res.status(400).send(err); } client.query('SELECT * FROM employee WHERE empid=$1', [1], function (err, result) { done(); // closing the connection; if (err) { console.log(err); res.status(400).send(err); } res.status(200).send(result.rows); }); }); }); app.listen(3000, function () { console.log('Server is running.. on Port 3000'); });
运行时出现了这个报错:
client.query('SELECT * FROM employee WHERE empid=$1', [1], function (err, result) { ^ TypeError: Cannot read property 'query' of null
请问该怎么解决这个问题?
嘿,这个问题我之前也碰到过!核心原因是当pg.connect失败时,client对象会变成null,但你没有在错误处理分支里终止后续代码执行,导致后面尝试调用client.query时触发了这个TypeError。给你几个具体的修复方案:
1. 先堵住最直接的漏洞:在错误分支添加return
修改你的pg.connect回调逻辑,当连接出错时,发送响应后直接返回,不要再执行后续的client.query:
pg.connect(connectionString, function (err, client, done) { if (err) { console.log("not able to get connection " + err); res.status(400).send(err); return; // 加上这行,阻止后续代码运行 } // 剩下的查询代码保持不变 });
这样就能避免在client为null的时候去调用它的方法了。
2. 检查Heroku PostgreSQL的连接配置
你提到connectionString是Heroku的数据库信息,这里要确认几个关键点:
- 不要手动拼接连接字符串!直接用
heroku config:get DATABASE_URL命令从终端获取官方的连接字符串,手动输入很容易写错用户名、密码或者主机地址。 - 确保你的Heroku PostgreSQL实例是活跃状态,没有被暂停,而且你的应用有访问这个数据库的权限(可以在Heroku控制台的数据库页面查看连接权限)。
3. 升级到更健壮的连接池写法(推荐)
旧版的pg.connect已经被官方废弃了,现在推荐使用连接池的方式,不仅能自动管理连接,还能避免很多手动处理连接的坑:
var express = require('express'); var { Pool } = require('pg'); var app = express(); // 使用连接池替代单个连接 const pool = new Pool({ connectionString: process.env.DATABASE_URL, // 用环境变量存储,不要硬编码 ssl: { rejectUnauthorized: false // Heroku的PostgreSQL需要这个配置,否则会SSL验证失败 } }); app.get('/', function (req, res) { pool.query('SELECT * FROM employee WHERE empid=$1', [1], (err, result) => { if (err) { console.error(err); return res.status(400).send(err); } res.status(200).send(result.rows); }); }); // 监听Heroku分配的端口,本地用3000 app.listen(process.env.PORT || 3000, () => { console.log('Server is running.. on Port', process.env.PORT || 3000); });
这种写法不需要手动调用done()来释放连接,连接池会自动处理,而且代码更简洁,也更适配Heroku的运行环境。
内容的提问来源于stack exchange,提问作者김기훈
相关产品推荐
相关产品推荐

