【问题标题】:TypeError: Class constructor model cannot be invoked without 'new'TypeError:没有'new'就不能调用类构造函数模型
【发布时间】:2021-05-24 15:43:40
【问题描述】:

我在一个应用中同时使用 Sequelize 以及 NodeJavaScript。如您所知,当您执行 sequelize-init 时,它会创建 configmigrationsmodelsseeders 文件夹。在 models 文件夹内,有一个 index.js 文件(由 cli 生成),负责从当前文件夹中读取所有模型及其关联:

index.js

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const sequelize = require('../database/connection');
const db = {};

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = require(path.join(__dirname, file))(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;

module.exports = db;

当我运行我的应用程序时,出现错误:TypeError: Class constructor model cannot be invoked without 'new' 在第 17 行,这是语句:var model = require(path. join(__dirname, file))(sequelize, Sequelize.DataTypes); 阅读了一些与此问题相关的posts,我发现我需要安装@babel/preset-env 包和@babel/cli, @babel/core, @babel/node。我还在根目录下创建了一个.babelrc文件,包含以下代码:

.babelrc

{
    "presets": [
      [
        "@babel/preset-env",
        {
          "targets": {
            "esmodules": true
          }
        }
      ]
    ]
}

并将package.jsonscripts 标签的start 选项更新为:"nodemon --exec babel-node app.js"(我不使用webpack)

但是当我运行应用程序时,错误仍然出现。我错过了什么或没有正确设置?

【问题讨论】:

  • 你不需要为 node.js 程序安装 babel!您只需要使用 new 而不是将类作为函数调用(就像错误告诉您的那样):const ThingThatIsAClass = require(path.join(__dirname, file)); const model = new ThingThatIsAClass(sequelize, Sequelize.DataTypes); 不要试图在一行代码上塞进太多东西。它很难阅读,而且很容易错过像这样的小错误。
  • 我为我的无能道歉,我不知道。我知道错误在于调用构造函数的方式,但从未拆分语句。谢谢!
  • 语句不用拆分,也可以写new (require(…))(…),但更难理解。
  • @CodiClone 不需要道歉,编程很难,缺乏经验不是道德上的失败:)

标签: javascript node.js ecmascript-6 sequelize.js babeljs


【解决方案1】:

注意:最后检查为什么部分!如果你想知道。

问题

问题是 ES6 类 => 没有将全部功能转译为 ES5! Sequelize 依赖于一些功能

或者

使用Sequelize.import 代替require!别! (Babel 或任何转译器与 require(或 es import)一起工作,以及 sequelize.import 工作如何导致问题!)!

回答

我猜你正在使用

export class Course extends Model {} // <== ES6 classes

Course.init({

是你的 babel 配置造成的!

你可以在这个 github 线程 comment 上检查一下

这对那个人有用

{
  "presets": [
    ["env", {
      "targets": {
        "node": "current"
      }
    }]
  ]
}

或者

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ]
}

comment

让 babel 使用 ES6 类!

请注意,另一方面您只需坚持sequelize.define()方式

export const User = sequelize.define('User', {
  // Model attributes are defined here
  firstName: {
    type: DataTypes.STRING,
    allowNull: false
  },

它将在 ES5 中正常工作!

不要使用 Sequelize.import 导入模型

如果你正在这样做,那就不要!使用require 或es import!转译器不直接处理 Sequelize.import!它似乎引起了问题

Comment 表明

对我来说,这是因为 ES6 和 Typescript

打字稿

默认目标是ES5

将其更改为 ES6+!一切都开始工作了!

例如

"target": "ES2021", 

带有 sequelize.define 的 ES5 工作

知道带有 sequelize.define 的 ES5 可以正常工作!

带有类扩展的 ES5 不起作用

插图

ES6+ 始终有效

为什么! Babel 通常不会正确转换!! ???

你可以在这个github上看到comment

事实证明,通过 babel 转译的 ES6 类不能扩展真正的 ES6 类(例如 The Sequelize.Model ES6 类)。
所以如果 MyEntity 被转译成 ES5,class MyEntity extends Sequelize.Model { ... } 将不起作用。

这里的stackoverflow答案解释得更好: https://stackoverflow.com/a/36657312/7668448

由于 ES6 类的工作方式,您不能使用转译类扩展原生类。如果您的平台支持原生类

您可以看到更多关于transpilation of ES6 Class to ES5 can be done to support full features and compatiblity 的原因和可能性的深度元素!在下面的链接中:

https://github.com/microsoft/TypeScript/issues/17088

https://github.com/microsoft/TypeScript/issues/15397

还有一篇文章 (comparing-different-ways-of-transpiling-es6-class-to-es5) 详细介绍了该主题

【讨论】:

  • 感谢您的详细解释!
猜你喜欢
  • 2018-11-12
  • 2019-04-21
  • 2021-05-17
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 2020-01-04
相关资源
最近更新 更多