module.filename未定义(Sequelize,Node.js)

时间:2017-09-24 17:06:59

标签: javascript node.js postgresql postgresql-9.6

我正在阅读Sequelize和Node.js的this教程。我在第4行得到以下错误:

TypeError:Path必须是字符串。收到未定义的

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/../config/config.json`)[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  sequelize = new Sequelize(
    config.database, config.username, config.password, config
  );
}
fs
  .readdirSync(__dirname)
  .filter(file =>
    (file.indexOf('.') !== 0) &&
    (file !== basename) &&
    (file.slice(-3) === '.js'))
  .forEach(file => {
    const model = sequelize.import(path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

似乎module.filename未定义。我不知道为什么会这样(我是Node的新手),与教程和我的应用程序的唯一区别是我不使用快速api(但GraphQL)和我的sequelize自动生成的文件夹位于。 ./postgres/而不是../

修改

如果我运行教程repo并打印module.filename,我会得到/Users/Creece/Downloads/postgres-express-node-tutorial-master/server/models/index.js

现在,如果我手动分配module.filename,如下所示:module.filename = '/Users/Creece/Downloads/express_graphql_hmr_article_boilterplate-master/server/postgres/models/index.js';(在分配基本名称常量之前),我在const model = ...行上得到一个新的奇怪错误:

Error: Cannot find module '/Users/Creece/Downloads/express_graphql_hmr_article_boilerplate-master/server/dist/postgres/models/todo.js'

请注意文件夹" dist"在上面的路径上是webpack(虽然不确定,但它不是我的)。

编辑2 :(关于我对@ NikMartin的评论&#39>

这是Sequelize ./postgres/models/todo.js自动生成的文件:

module.exports = (sequelize, DataTypes) => {

  const Todo = sequelize.define('Todo', {
    title: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  });



  Todo.associate = (models) => {
    Todo.hasMany(models.TodoItem, {
      foreignKey: 'todoId',
      as: 'todoItems',
    });
  };
  return Todo;

};

解决方案(根据接受的答案):

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
//const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/../config/config.json`)[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  sequelize = new Sequelize(
    config.database, config.username, config.password, config
  );
}

const models = [
  require('./Todo')(sequelize, Sequelize),
  require('./TodoItem')(sequelize, Sequelize),
];

models.forEach(model => {
  db[model.name] = model;
});

models.forEach(model => {

  if (db[model.name].associate) {
    console.log("entered");
    db[model.name].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

2 个答案:

答案 0 :(得分:1)

关于module.filename问题,您可以阅读此讨论或仅阅读该评论:https://github.com/webpack/webpack/issues/1599#issuecomment-328540024

报价:

  

aprilmintacpineda评论

     

对于那些遇到此问题的人,还可以注意到,如果捆绑了文件,module.filename将是未定义的。在我的情况下它是未定义的,我通过简单地用__filename替换它来修复它,产生相同的结果。

因此,您应该能够将path.basename(module.filename);替换为path.basename(__filename);

但它仍然是/ dist文件夹中的捆绑js文件,你的模型在/ postgres / models文件夹中,据我所知。

我在这里看到两个选项:

1)不要自动加载模型,而是直接需要所有必要的模型。

假设此文件的路径为/postgres/models/index.js且实际模型位于同一文件夹中 未经过测试

const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/../config/config.json`)[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  sequelize = new Sequelize(
    config.database, config.username, config.password, config
  );
}

// removed autoloading block

// setting the list of used models
const models = [
  require('./TodoItem')(sequelize, Sequelize),
  require('./Comment')(sequelize, Sequelize)
];

// registering models by their names
models.forEach(model => {
  db[model.name] = model;
});

// using registered models to set up relations
models.forEach(model => {
  if (model.associate) {
    model.associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

这意味着灵活性会降低,但捆绑的代码会开始使用捆绑的模型。我认为对于需要一些"外部"的dist代码来说,这不是最好的选择。 (缺少内部模型)非配置js文件工作。

2)加载不是来自当前文件夹但来自已定义文件的文件。

  • /postgres/models/index.js从models文件夹移到/postgres/index.js(因此模型文件夹只包含实际的模型文件)
  • 从文件中删除basename
  • 而不是.readdirSync(__dirname)使用.readdirSync(__dirname + "/../postgres/models")
  • 删除(file !== basename) &&检查(因为没有必要)

无论哪种方式,替换模块的属性(module.filename)都不应该是一个解决方案。

答案 1 :(得分:0)

可以这样简化:

const config = require('../config/config')['development']
const {Sequelize} = require('sequelize');
const sequelize = new Sequelize(config['dbUrl']);
const db = {};
const models = [];

sequelize.authenticate()
    .then(() => console.log('Connection has been established successfully.'))
    .catch(err => console.error('Unable to connect to the database:', err));

const modules = [
    require('./user'),
    require('./post'),
    require('./comment')
]

modules.forEach(module => {
    const model = module(sequelize, Sequelize)
    db[model.name] = model
    models.push(model)
});

models.forEach(model => {
    if (db[model.name].associate) {
        db[model.name].associate(db)
    }
});

module.exports = {...db, sequelize, Sequelize};