【问题标题】:Nodejs "is not a constructor" error when two files are required into each other当两个文件相互需要时,Nodejs“不是构造函数”错误
【发布时间】:2021-05-30 20:17:27
【问题描述】:

我需要将两个 js 对象(播放器和房间)放入彼此的文件中。但是当我这样做时,发生了意外错误。

app.js:

const Player = require("./Player").Player

let player = new Player()

Player.js:

const Room = require ("./Room").Room
let room = new Room()

const Player = function () {
    let room = new Room()
}

exports.Player = Player

Room.js:

const Player = require("./Player").Player
let player = new Player()

const Room = function () {
    
}

exports.Room = Room

还有错误:

/home/mosi/Github/test/Room.js:2
let player = new Player()
             ^

TypeError: Player is not a constructor
    at Object.<anonymous> (/home/mosi/Github/test/Room.js:2:14)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (/home/mosi/Github/test/Player.js:1:14)
    at Module._compile (internal/modules/cjs/loader.js:778:30)

【问题讨论】:

标签: javascript node.js object constructor


【解决方案1】:

因为它们相互依赖,所以您的模块是循环的;请参阅 Node.js 文档 here。正如他们所说,“需要仔细规划才能使循环模块依赖项在应用程序中正常工作。” :-)

如果您可以避免在一个循环中使用模块,那通常是最好的。

使用 ESM,“所有”你要做的就是不要在 Player.jsRoom.js 的顶层使用 PlayerRoom,但使用 CJS 模块,你也正在使用你不仅如此。我不是整理 CJS 模块中的循环的专家,但我认为您需要做的主要事情是不要尝试立即获取 PlayerRoom 导出。让模块先完成加载。例如:

app.js:

const Player = require("./Player").Player;

let player = new Player();

Player.js:

// Import the module exports object, but don't grab its `Room` property yet
const RoomMod = require ("./Room");
// Don't do this at the top level: let room = new Room()

const Player = function () {
    // Now it's safe to use the `Room` property
    let room = new RoomMod.Room();
};

exports.Player = Player;

Room.js:

// Get the module exports object, but don't try to get the `Player` property yet
const PlayerMod = require("./Player");
// Don't do this at the top level: let player = new Player()

const Room = function () {
    
};

exports.Room = Room;

对于它的价值,如果您使用 ESM(JavaScript 标准模块),您不必只导入模块,然后再使用属性,因为使用 ESM,导入的绑定是有效的。因此,尽管您仍然必须避免在 Room.jsPlayer.js 的顶层使用 PlayerRoom,但您可以在不需要模块命名空间对象(ESM 等效于 CJS 导出对象)的情况下导入它们:

app.js:

import { Player } from "./Player.js";

let player = new Player();

Player.js:

import { Room } from "./Room.js";

export const Player = function () {
    let room = new Room()
};

Room.js:

import { Player } from "./Player.js";

export const Room = function () {
    
};

【讨论】:

    猜你喜欢
    • 2014-08-04
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多