ReferenceError: Cannot access 'Player' before initialization
ReferenceError: Cannot access 'Player' before initialization
所以我一直在带有 ESM 模块加载器的 Nodejs 上使用带有 import/export 的 ES6 样式语法。一切都很好,直到我开始收到与导入有关的错误。
错误信息如下:
joseph@InsaneMachine:~/placeholder2/main-server$ npm start
> main-server@1.0.0 start /home/joseph/placeholder2/main-server
> nodemon --experimental-modules src/index.mjs
[nodemon] 1.19.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node --experimental-modules src/index.mjs`
(node:16942) ExperimentalWarning: The ESM module loader is experimental.
file:///home/joseph/placeholder2/main-server/src/games/game-player.mjs:3
export default class GamePlayer extends Player
^
ReferenceError: Cannot access 'Player' before initialization
at file:///home/joseph/placeholder2/main-server/src/games/game-player.mjs:3:41
at ModuleJob.run (internal/modules/esm/module_job.js:109:37)
at async Loader.import (internal/modules/esm/loader.js:132:24)
[nodemon] app crashed - waiting for file changes before starting...
这是播放器文件(基础 class):
import PasswordHash from 'password-hash';
import GamesService from '../games/games.service.mjs';
import PlayersService from './players.service.mjs';
import QueueingService from '../queueing/queueing.service.mjs';
export default class Player
{
constructor(object)
{
Object.assign(this, JSON.parse(JSON.stringify(object)));
}
get id()
{
return this._id.toString();
}
equals(other)
{
if(other.id != null)
return other.id == this.id;
return false;
}
checkPassword(password)
{
return PasswordHash.verify(password, this.password);
}
online()
{
return PlayersService.consumer.isPlayerOnline(this);
}
inQueue()
{
return QueueingService.queued(this);
}
inGame()
{
return GamesService.getActiveGameByPlayer(this) != null;
}
reduce()
{
return {
id: this.id,
username: this.username,
email: this.email,
admin: this.admin,
online: this.online(),
in_queue: this.inQueue(),
in_game: this.inGame(),
};
}
static hashPassword(password)
{
return PasswordHash.generate(password);
}
static schema = {
username: String,
password: String,
email: String,
email_confirmed: Boolean,
admin: Boolean,
}
}
和GamePlayer (Child Class):
import Player from '../players/player.mjs';
export default class GamePlayer extends Player
{
constructor(player, token)
{
super(player);
this.token = token;
}
}
以及项目的层次结构:
src/
-- games/
-- -- game-player.mjs
-- -- ...
players/
-- -- player.mjs
-- -- ...
-- ...
我该如何解决这个导入问题,除非这是其他问题?
编辑:据我所知,我没有使用 Babel,我使用的是 Node 提供的 --external-modules。不确定它是如何工作的。
从您的 Babel 配置中删除 es2015。
class 扩展原生 ES6 class 并且 Babel 转译为最有可能导致问题的 ES
我去了 Node.JS 论坛并询问可能是什么问题。根本不是 babel 问题,只是循环依赖。例如:
// A.js
import B from './B.js'
export default class A{}
// B.js
import A from './A.js'
export default class B extends A{}
抱歉,没有足够的信息来解决这个问题。我在 node.js github 上得到了很多帮助,有人查看了我在 github 上的项目,最终找到了一个两个模块相互指向的实例。
你的 import
中的依赖项可能太难解决,所以它放弃了,让你在需要定义 GamePlayer
的地方 Player
未初始化.
正如我在另一个答案的评论中提到的,import
可以以“循环”方式使用,但 Node.js 不能总是解开依赖关系。
在我的例子中,一个文件中的 class 和另一个文件中的子 class 没有问题,它们彼此 import
,并且它是很难说到底哪里变得太复杂了,但这是我所拥有的破坏它的简化版本:
// server.js
import Acorn from './acorn.js';
import Branch from './branch.js';
class Server {
...
}
// universe.js
import Acorn from './acorn.js';
import Branch from './branch.js';
import Thing from './thing.js';
export default class Universe {
things(type) {
if (Thing.klass[type]) {
...
}
}
...
}
// acorn.js
import Thing from './thing.js';
export default class Acorn extends Thing {
...
}
// branch.js
import Thing from './thing.js';
export default class Branch extends Thing {
...
}
// thing.js
import Acorn from './acorn.js';
import Branch from './branch.js';
export default class Thing {
static klass(type) {
const klass = {acorn: Acorn, branch: Branch};
...
return klass;
}
constructor(...) {
this.type = this.constructor.name.toLowerCase();
...
}
...
}
我在浏览器和服务器端使用相同的代码 Node.js,所以我也用 Babel 转译它,它处理一切都很好。但 Node 可能还有其他限制因素,使其变得更加困难,因为至少就导入而言,它与浏览器(和其他浏览器)处于不同的轨道上,现在正试图弥合差距。而且这个结可能比肉眼看起来更纠结。
最后我放弃了我的模式中最循环的部分,这是我在 Thing 本身中引用 Thing subclasses 的部分。我将其提取为“类工厂”模式,其中工厂知道 Thing subclasses,但 Thing 及其子classes 不需要工厂。
所以我一直在带有 ESM 模块加载器的 Nodejs 上使用带有 import/export 的 ES6 样式语法。一切都很好,直到我开始收到与导入有关的错误。
错误信息如下:
joseph@InsaneMachine:~/placeholder2/main-server$ npm start
> main-server@1.0.0 start /home/joseph/placeholder2/main-server
> nodemon --experimental-modules src/index.mjs
[nodemon] 1.19.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node --experimental-modules src/index.mjs`
(node:16942) ExperimentalWarning: The ESM module loader is experimental.
file:///home/joseph/placeholder2/main-server/src/games/game-player.mjs:3
export default class GamePlayer extends Player
^
ReferenceError: Cannot access 'Player' before initialization
at file:///home/joseph/placeholder2/main-server/src/games/game-player.mjs:3:41
at ModuleJob.run (internal/modules/esm/module_job.js:109:37)
at async Loader.import (internal/modules/esm/loader.js:132:24)
[nodemon] app crashed - waiting for file changes before starting...
这是播放器文件(基础 class):
import PasswordHash from 'password-hash';
import GamesService from '../games/games.service.mjs';
import PlayersService from './players.service.mjs';
import QueueingService from '../queueing/queueing.service.mjs';
export default class Player
{
constructor(object)
{
Object.assign(this, JSON.parse(JSON.stringify(object)));
}
get id()
{
return this._id.toString();
}
equals(other)
{
if(other.id != null)
return other.id == this.id;
return false;
}
checkPassword(password)
{
return PasswordHash.verify(password, this.password);
}
online()
{
return PlayersService.consumer.isPlayerOnline(this);
}
inQueue()
{
return QueueingService.queued(this);
}
inGame()
{
return GamesService.getActiveGameByPlayer(this) != null;
}
reduce()
{
return {
id: this.id,
username: this.username,
email: this.email,
admin: this.admin,
online: this.online(),
in_queue: this.inQueue(),
in_game: this.inGame(),
};
}
static hashPassword(password)
{
return PasswordHash.generate(password);
}
static schema = {
username: String,
password: String,
email: String,
email_confirmed: Boolean,
admin: Boolean,
}
}
和GamePlayer (Child Class):
import Player from '../players/player.mjs';
export default class GamePlayer extends Player
{
constructor(player, token)
{
super(player);
this.token = token;
}
}
以及项目的层次结构:
src/
-- games/
-- -- game-player.mjs
-- -- ...
players/
-- -- player.mjs
-- -- ...
-- ...
我该如何解决这个导入问题,除非这是其他问题?
编辑:据我所知,我没有使用 Babel,我使用的是 Node 提供的 --external-modules。不确定它是如何工作的。
从您的 Babel 配置中删除 es2015。 class 扩展原生 ES6 class 并且 Babel 转译为最有可能导致问题的 ES
我去了 Node.JS 论坛并询问可能是什么问题。根本不是 babel 问题,只是循环依赖。例如:
// A.js
import B from './B.js'
export default class A{}
// B.js
import A from './A.js'
export default class B extends A{}
抱歉,没有足够的信息来解决这个问题。我在 node.js github 上得到了很多帮助,有人查看了我在 github 上的项目,最终找到了一个两个模块相互指向的实例。
你的 import
中的依赖项可能太难解决,所以它放弃了,让你在需要定义 GamePlayer
的地方 Player
未初始化.
正如我在另一个答案的评论中提到的,import
可以以“循环”方式使用,但 Node.js 不能总是解开依赖关系。
在我的例子中,一个文件中的 class 和另一个文件中的子 class 没有问题,它们彼此 import
,并且它是很难说到底哪里变得太复杂了,但这是我所拥有的破坏它的简化版本:
// server.js
import Acorn from './acorn.js';
import Branch from './branch.js';
class Server {
...
}
// universe.js
import Acorn from './acorn.js';
import Branch from './branch.js';
import Thing from './thing.js';
export default class Universe {
things(type) {
if (Thing.klass[type]) {
...
}
}
...
}
// acorn.js
import Thing from './thing.js';
export default class Acorn extends Thing {
...
}
// branch.js
import Thing from './thing.js';
export default class Branch extends Thing {
...
}
// thing.js
import Acorn from './acorn.js';
import Branch from './branch.js';
export default class Thing {
static klass(type) {
const klass = {acorn: Acorn, branch: Branch};
...
return klass;
}
constructor(...) {
this.type = this.constructor.name.toLowerCase();
...
}
...
}
我在浏览器和服务器端使用相同的代码 Node.js,所以我也用 Babel 转译它,它处理一切都很好。但 Node 可能还有其他限制因素,使其变得更加困难,因为至少就导入而言,它与浏览器(和其他浏览器)处于不同的轨道上,现在正试图弥合差距。而且这个结可能比肉眼看起来更纠结。
最后我放弃了我的模式中最循环的部分,这是我在 Thing 本身中引用 Thing subclasses 的部分。我将其提取为“类工厂”模式,其中工厂知道 Thing subclasses,但 Thing 及其子classes 不需要工厂。