You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

部署至Heroku的Express API出现str.charAt is not a function错误,带参数路由无法正常响应

排查与解决API路由无响应及str.charAt is not a function错误

让我们一步步拆解你的问题,找到根源并解决:

核心错误原因分析

你遇到的str.charAt is not a function错误,结合路由无响应的表现,本质是数据库连接配置错误引发的连锁问题,再加上错误处理不完善,导致客户端一直处于等待状态。具体来说:

1. 数据库环境配置逻辑完全写反

看你的db.js代码:

const conn = new Pool({
  connectionString: process.env.NODE_ENV === "production" ? devConfig : proConfig
});

这里的逻辑搞反了!当NODE_ENVproduction(也就是Heroku生产环境)时,你用的是本地开发的devConfig;而本地开发时,反而用的是生产环境的proConfig(依赖DATABASE_URL变量)。本地如果没正确配置DATABASE_URL,数据库连接会直接失败,执行pool.query时就会抛出错误。

2. 开发环境连接字符串存在多余空格

你的devConfig里:

const devConfig = `postgresql://${process.env.PG_USER}: ${process.env.PG_PASSWORD}@${process.env.PG_HOST}: ${process.env.PG_PORT}/${process.env.PG_DATABASE}`;

注意${process.env.PG_PASSWORD}前的空格,还有${process.env.PG_PORT}前的空格——这些多余的空格会导致PostgreSQL无法正确解析连接字符串,进而触发字符串处理相关的错误(也就是你看到的str.charAt is not a function)。

3. 错误处理未给客户端返回响应

在API路由的catch块里,你只打印了error.message,但没有给客户端发送任何响应:

catch (error) {
  console.log(error.message);
};

这就导致浏览器发起请求后,一直等待服务器返回结果,但服务器永远不会响应,所以你看到请求无响应、控制台无报错的现象。

分步修复方案

1. 修正数据库连接配置(db.js)

把环境判断逻辑反过来,同时去掉连接字符串里的多余空格:

const { Pool } = require('pg');
require("dotenv").config();

// 去掉多余空格,确保连接字符串格式正确
const devConfig = `postgresql://${process.env.PG_USER}:${process.env.PG_PASSWORD}@${process.env.PG_HOST}:${process.env.PG_PORT}/${process.env.PG_DATABASE}`;
const proConfig = { connectionString: process.env.DATABASE_URL };

// 修正逻辑:生产环境用proConfig,开发环境用devConfig
const conn = new Pool({
  connectionString: process.env.NODE_ENV === "production" ? proConfig.connectionString : devConfig
});

module.exports = conn;

本地开发时,确保.env文件里的PG_USERPG_PASSWORDPG_HOSTPG_PORTPG_DATABASE变量都正确配置,且本地PostgreSQL服务正在运行。

2. 完善错误处理,给客户端返回响应

修改API路由的catch块,在打印完整错误的同时,给客户端返回500错误和错误信息:

app.get("/data/:date/:tier", async (req, res) => {
  try {
    const { date, tier } = req.params;
    const allData = await pool.query(
      "SELECT * FROM smogon_usage_stats WHERE date=$1 AND tier=$2",
      [date, tier]
    );
    const results = allData.rows;
    const output = {
      "data": Object.fromEntries(
        results.map(
          item => [item.pokemon, item]
        )
      )
    };
    res.json(output);
  } catch (error) {
    console.error(error); // 打印完整错误信息,方便排查
    res.status(500).json({ error: error.message }); // 给客户端返回错误响应
  };
});

这样浏览器就能收到明确的错误提示,而不是一直处于无响应状态。

3. 本地测试验证

  1. 启动本地PostgreSQL服务,确认.env配置正确
  2. 重新运行node index.js
  3. 访问localhost:5000/data/2018-10/gen6ou,现在应该能看到正确的响应,或者明确的错误提示

4. Heroku部署注意事项

  • 确保已在Heroku上添加PostgreSQL插件:执行heroku addons:create heroku-postgresql:hobby-dev
  • Heroku会自动设置NODE_ENVproduction,无需手动配置
  • 部署前可运行heroku run node -e "console.log(process.env.DATABASE_URL)",验证DATABASE_URL是否正常存在

额外优化建议

  • 本地开发时,安装cross-env包,在package.json脚本里设置开发环境:
    "scripts": {
      "start": "node index.js",
      "dev": "cross-env NODE_ENV=development node index.js"
    }
    
  • console.error打印错误,这样错误信息会在终端高亮显示,更易识别

内容的提问来源于stack exchange,提问作者nos codemos

火山引擎 最新活动