Express中使用内联import报错:app.use()需中间件函数
TypeError: app.use() requires a middleware function(ES6内联import替换问题)
问题描述
将项目切换至ES6语法,替换所有内联require为import时,顶层import正常,但替换内联调用时出现错误:
TypeError: app.use() requires a middleware function
项目主文件代码:
// We need these modules to be present. import path from "path"; import dotEnv from "dotenv"; import express from "express"; import { fileURLToPath } from 'url'; import connectToDatabase from "./database.js"; import morganMiddleware from "./middlewares/morgan.middleware.js"; // Initialise exress const app = express(); // Initialise dotEnv; dotEnv.config(); // Define file and directory path const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Load environment variables const PORT = process.env.PORT || 1313; // Properly parse the json and urlencoed data app.use(express.urlencoded({ extended: false })); app.use(express.json()); // Add the morgan middleware app.use(morganMiddleware); // When we respond with a json object, indent every block with 4 spaces. app.set("json spaces", 4); // Where should we look for the static files app.use(express.static(path.join(__dirname, "../public"))); //Load the different routes app.use(import("./controllers/index.js")); // 出错的行 // Connect to database connectToDatabase(); // Custom Error handling app.use((req, res) => { res.status(404).json({ type: "error", message: "404: Page not Found"}); }); app.use((error, req, res, next) => { res.status(500).json({ type: "error", message: "500: Internal Server Error"}); }); // Start the server app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
controllers/index.js代码:
// Loading the modules import { Router } from "express"; const router = Router() // Load the models import ProjectsData, { addProject } from "../models/projects.js"; router.post("/", (req, res) => { res.send("Cool. We are working. Now you can proceed to cry."); }); export default router;
原因分析
import()是ES6的动态导入语法,它的返回值是一个Promise对象,而非直接获取模块导出的内容。而app.use()要求传入的是中间件函数(或Router实例,本质属于中间件),直接将Promise传递给它,自然不符合参数要求,触发错误。
解决方案
方案1:改用顶层静态导入(推荐)
路由模块属于应用启动时必须加载的核心模块,不需要动态导入。将路由模块改为顶层静态导入,直接获取导出的Router实例:
// 在文件顶部添加静态导入 import indexRouter from "./controllers/index.js"; // ... 其他代码不变 // 替换原来的动态导入行 app.use(indexRouter);
方案2:动态导入时处理Promise(按需加载场景)
如果确实需要动态导入(比如按需加载路由的场景),需要等待Promise resolve后获取导出的Router实例,可通过async/await实现:
// 将启动逻辑封装为异步函数 async function startServer() { // ... 所有初始化代码(除了路由加载和启动服务)保持不变 // 等待动态导入完成,获取默认导出的Router const { default: indexRouter } = await import("./controllers/index.js"); app.use(indexRouter); // 错误处理和启动服务放在异步函数内 app.use((req, res) => { res.status(404).json({ type: "error", message: "404: Page not Found"}); }); app.use((error, req, res, next) => { res.status(500).json({ type: "error", message: "500: Internal Server Error"}); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); } // 启动服务 startServer();
内容的提问来源于stack exchange,提问作者CrumpledMemories
相关产品推荐
相关产品推荐

