Node ESM模块搭配Sequelize v6初始化报错:sequelize.import不是函数
解决Sequelize v6 ESM环境下替代
sequelize.import的问题 Sequelize v6已移除sequelize.import方法,传统require加载方案无法适配ESM模块系统,以下是针对你的代码的具体改造方案:
1. 统一模型文件的导出格式
确保所有模型文件(如User.js、Message.js)采用ESM默认导出,格式示例:
// models/User.js示例 export default (sequelize, DataTypes) => { const User = sequelize.define('User', { username: { type: DataTypes.STRING, allowNull: false } // 其他字段定义 }); User.associate = (db) => { User.hasMany(db.Message); // 关联关系定义 }; return User; };
2. 改造models/index.js的模型加载逻辑
由于ESM的import()是异步操作,需要将syncDb改为异步函数,替换同步forEach为支持await的循环:
import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import Sequelize from 'sequelize'; import process from 'process'; const env = process.env.NODE_ENV || 'development'; import configDB from '../config/config.json' assert { type: "json" }; const config = configDB[env]; const db = {}; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const basename = path.basename(__filename); // 改为异步函数 export default async function syncDb() { let sequelize; if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { sequelize = new Sequelize(config.database, config.username, config.password, config); } // 筛选模型文件列表 const modelFiles = fs .readdirSync(__dirname) .filter(file => { return ( file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' && file.indexOf('.test.js') === -1 ); }); // 用for...of循环替代forEach,支持await异步加载 for (const file of modelFiles) { const modelModule = await import(path.join(__dirname, file)); const model = modelModule.default(sequelize, Sequelize.DataTypes); db[model.name] = model; } // 执行模型关联 Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); db.sequelize = sequelize; db.Sequelize = Sequelize; // 异步验证数据库连接 try { await db.sequelize.authenticate(); console.log('Database connected!!'); } catch (err) { console.error('Database connection failed:', err); } // 如需自动同步模型结构,可添加该行 // await db.sequelize.sync(); return db; }
3. 调整Server.js的调用逻辑
syncDb变为异步函数后,需用await调用,并将启动逻辑包裹在async函数中:
import { ApolloServer } from '@apollo/server'; import { startStandaloneServer } from '@apollo/server/standalone'; import syncDb from './models/index.js'; async function startServer() { // 等待数据库初始化完成 await syncDb(); // GraphQL schema定义 const typeDefs = `#graphql type Query { hello: String } `; // 解析器定义 const resolvers = { Query: { hello: () => 'world', }, }; const server = new ApolloServer({ typeDefs, resolvers, }); const { url } = await startStandaloneServer(server); console.log(`🚀 Server ready at ${url}`); } // 启动服务并捕获错误 startServer().catch(err => console.error('Server startup error:', err));
核心逻辑说明
- 用ESM动态
import()替代废弃的sequelize.import,实现异步加载模型模块 - 模型文件保持接收
sequelize和DataTypes的函数格式,与原逻辑兼容 - 改用for...of循环遍历文件,解决forEach无法处理异步await的问题
内容的提问来源于stack exchange,提问作者PhilibertEtienne
相关产品推荐
相关产品推荐

