You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Express的API GET请求中运行导入的异步函数遇阻

异步函数与Express路由结合问题解决方法

问题核心

你遇到的问题是异步函数未正确处理,导致Express路由直接返回未完成的Promise对象(浏览器显示{}),控制台先输出Promise { <pending> },后续才拿到数据库查询结果。根源在于:

  1. showContent作为async函数,调用后返回Promise,直接res.send会把Promise对象序列化输出
  2. getContent的Promise封装逻辑错误,没有在数据库查询完成后正确resolve结果
  3. showContent未返回查询到的结果,上层无法获取有效数据

修复后的数据库脚本(model.js)

import sqlite3 from "sqlite3";

const db = new sqlite3.Database("path/to/my/db");

// 重构getContent:正确封装Promise,查询完成后resolve结果
export default function getContent(sqlQuery) {
  return new Promise((resolve, reject) => {
    db.all(sqlQuery, [], (err, rows) => {
      if (err) {
        console.error(err);
        reject(err); // 错误时reject,方便上层捕获处理
      } else {
        // 提取所有page_content返回,可根据需求调整为单个结果
        const content = rows.map(row => row.page_content);
        resolve(content);
      }
    });
  });
}

// 重构showContent:返回查询结果,同时捕获错误
export async function showContent(sqlQuery) {
  try {
    const result = await getContent(sqlQuery);
    console.log("Result:", result);
    return result; // 必须返回结果,上层才能拿到有效数据
  } catch (err) {
    console.error("查询失败:", err);
    throw err; // 抛出错误让Express错误处理中间件处理
  }
}

修复后的路由脚本

import express from "express";
import { showContent } from "../model/model.js"; // 改为解构导入

const router = express.Router();

router.get("/", function (req, res) {
  res.render("../pages/start.ejs");
});

// 路由处理函数声明为async,用await等待异步结果
router.get("/:id", async function (req, res, next) {
  const id = req.params.id; // 用const声明,避免全局变量污染
  let sqlQuery = `SELECT page_content FROM ${id} WHERE page_name = "about";`;
  
  try {
    const content = await showContent(sqlQuery);
    console.log("1", content); // 现在会输出实际查询结果
    res.send(content); // 返回有效数据给前端
  } catch (err) {
    next(err); // 将错误传递给Express内置错误处理中间件
  }
});

export default router;

关键注意事项

  • async函数的返回值:所有async函数默认返回Promise,必须用await或.then()才能获取内部结果,不能直接当作普通值使用
  • Promise封装规范:异步操作(如数据库查询)的Promise要在回调函数内调用resolve/reject,而非直接resolve异步函数本身
  • Express异步路由:包含异步操作的路由处理函数必须声明为async,并用try/catch捕获错误,通过next(err)传递错误
  • 防范SQL注入:当前代码直接用${id}拼接SQL语句,存在严重的SQL注入风险,建议改用参数化查询:
    // 参数化查询示例
    let sqlQuery = `SELECT page_content FROM ? WHERE page_name = ?;`;
    const content = await getContent(sqlQuery, [id, "about"]);
    
    // 对应修改getContent的参数
    export default function getContent(sqlQuery, params) {
      return new Promise((resolve, reject) => {
        db.all(sqlQuery, params, (err, rows) => {
          // 原有逻辑不变
        });
      });
    }
    

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:35:23