【问题标题】:"Cannot access ModuleName before initialization" using import使用导入“无法在初始化之前访问 ModuleName”
【发布时间】:2021-09-21 11:44:53
【问题描述】:

我正在为 Web 应用程序制作 API,但在尝试导入模块时遇到了一个奇怪的问题。我有一个文件夹,其中包含用于从数据库中获取数据的一堆模型,并且我有一个名为“global”的文件夹,其中包含整个项目中使用的各种模块。

/
  /api
    /models
      /Users.js
      /Trainings.js
      /TrainingsTypes.js
      /TrainingsSubtypes.js
  /global
    /Functions.js

某些模型导入其他模型来检查ID,获取数据等。我在Functions.js中做了一个功能,它也需要一些模型才能工作。所以基本上,导入依赖项看起来像: 我必须承认,当这样显示时,这有点糟糕。但这是我的问题。只要Functions.js 不导入Users.js,一切都很好。 API 运行良好,完全没有崩溃。但是,如果我在Functions.js 中导入Users.js,我会立即收到此错误:

ReferenceError: Cannot access 'Users' before initialization
    at file:///C:/Users/USERNAME/Desktop/project-api/global/Functions.js:30:10
    at ModuleJob.run (internal/modules/esm/module_job.js:169:25)
    at async Loader.import (internal/modules/esm/loader.js:177:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)

Functions.js 的代码如下(我在第 30 行加了注释):

import check from "checkers";
import Users from "../api/models/Users.js";
import Trainings from "../api/models/Trainings.js";
import TrainingsTypes from "../api/models/TrainingsTypes.js";
import TrainingsSubtypes from "../api/models/TrainingsSubtypes.js";

/*****************************************************
 * SQL Queries
 *****************************************************/

export function fieldsToUpdate(fields) {...}

const fillers = {
    "user": Users, // Line 30
    "trainer": Users,
    "type": TrainingsTypes,
    "subtype": TrainingsSubtypes
};

export async function fillIDs(db, response) {...}

此外,导入本身不会导致问题。如果我从fillers 对象中删除Users,仍然没有崩溃。我已经看到这可能是一个循环依赖问题,但有人说 Node 可以处理这个问题。我必须补充一点,我真的需要fillIDs() 中的所有模型,所以我无法删除所有导入,我不想在每个模型中复制/粘贴此代码。一定有解决办法,但我需要一些帮助。

您知道如何解决这个问题吗? 谢谢

编辑 1: Users.js 导入这些模块:

import bcrypt from "bcryptjs";
import generatePwd from "generate-password";
import { v4 as uuidv4 } from "uuid";
import check from "checkers";
import { fieldsToUpdate, fillIDs } from "../../global/Functions.js";
import { arrayToSerialComma } from "../../global/Converters.js";
import APIResp from "../../global/APIResp.js";
import Mailer from "../../global/Mailer.js";
import Genders from "./Genders.js";
import Roles from "./Roles.js";
import Tokens from "./Tokens.js";
import { Passwords } from "../../config/config.js";

编辑 2: Users.js是这样导出的:

const Users = {
    isValid,
    add,
    logIn, getAll, getById, getByEmail, hasForgotPassword, getRolesOf,
    update, updatePwd, passwordForgotten,
    delete: del,
    Trainers: {
        getById: getTrainerById,
        getAll: getAllTrainers
    }
};

export default Users;

【问题讨论】:

  • User.js 导入了什么?
  • 我正在编辑我的帖子以添加它们
  • 最简单的解决方案是将fillers 对象移动到正在使用它的函数内。
  • 这并不理想,但我想我别无选择。我现在就这样做,谢谢
  • 另一种选择是安排导入顺序,以便最后执行创建该对象的模块,但这是不平凡的,容易破坏,而且您没有显示足够的代码甚至判断它是否可能。

标签: javascript node.js es6-modules circular-dependency


【解决方案1】:

我设法部分解决了我的问题。我在global 中创建了一个文件,导出了该文件夹中的所有文件,并为models 做了同样的事情。

// ROOT/global/global.js
export { default as APIResp } from "./APIResp.js";
export { default as SQLFunctions } from "./SQLFunctions.js";
export { default as Mailer } from "./Mailer.js";
export { default as ModuleConsole } from "./ModuleConsole.js";

// ROOT/api/models/models.js
export { default as Users } from "./Users.js";
export { default as Genders } from "./Genders.js";
export { default as Roles } from "./Roles.js";
export { default as Tokens } from "./Tokens.js";
export { default as Trainings } from "./Trainings.js";
export { default as TrainingsTypes } from "./TrainingsTypes.js";
export { default as TrainingsSubtypes } from "./TrainingsSubtypes.js";

我还删除了前端和后端都需要的一些功能,并将它们移至外部模块。我使用madge 生成依赖图。

正如我们所见,它还不完美。所有模型文件实际上都处于一个很大的循环依赖关系中,但它比以前更干净,并且没有更多的崩溃。 这可能会对性能产生影响,对此我必须小心。

我暂时将此答案标记为正确,如果其他人或我发现了什么,我可能会更改它。

【讨论】:

    猜你喜欢
    • 2020-09-17
    • 1970-01-01
    • 2020-12-29
    • 2021-09-10
    • 2020-10-23
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多