gpt4 book ai didi

javascript - 复杂循环 Node 模块依赖抛出 "TypeError: The super constructor to ' 继承'必须有一个原型(prototype)“

转载 作者:搜寻专家 更新时间:2023-10-31 23:08:30 24 4
gpt4 key购买 nike

我有一个复杂的 Node SDK 项目,它使用一些类继承来尝试静态化 Javascript。我正在使用 Node 的模块缓存行为为 SDK(Project 类,ProjectClient 的共享实例)创建类似单例的行为。要初始化,它看起来像这样:

var Project = require('./project'),
Project.init(params)
// Project is now an instance of ProjectClient

我还有一些数据对象类型类:Entity(标准解析的 JSON 有效负载对象)和 User(一种包含用户的特殊类型的实体属性)。

ProjectClient 类有几个允许调用 RESTful API 的方法,例如Project.GET()Project.PUT()。这些在实例化 Project“singleton”时工作得很好。

我现在正在尝试创建附加到 Entity 的便捷方法,它将利用 ProjectClient 的 RESTful 操作,例如Entity.save()Entity.refresh()

当我尝试将 Project 导入 Entity 时:

var Project = require('../project')

我得到:

TypeError: The super constructor to `inherits` must have a prototype.
at Object.exports.inherits (util.js:756:11)

故障排除让我发现这与 User 中的 util.inherits(ProjectUser, ProjectEntity) 相关,因为如果我将其注释掉,我会得到这个:

Uncaught TypeError: ProjectEntity is not a function

inherits 是怎么回事?为什么它认为 Entity 没有原型(prototype)?我最好的猜测是,这与我在其他模块中递归嵌套模块这一事实有关(不好,我知道),但我什至尝试在各种类中做类似的事情但无济于事:

module.exports = _.assign(module.exports, **ClassNameHere**)

这是每个类的一些精简代码:

实体

var Project = require('../Project'),
_ = require('lodash')

var ProjectEntity = function(obj) {
var self = this

_.assign(self, obj)

Object.defineProperty(self, 'isUser', {
get: function() {
return (self.type.toLowerCase() === 'user')
}
})

return self
}

module.exports = ProjectEntity

用户(实体的子类)

var ProjectEntity = require('./entity'),
util = require('util'),
_ = require('lodash')

var ProjectUser = function(obj) {

if (!ok(obj).has('email') && !ok(obj).has('username')) {
// This is not a user entity
throw new Error('"email" or "username" property is required when initializing a ProjectUser object')
}

var self = this

_.assign(self, ProjectEntity.call(self, obj))

return self
}

util.inherits(ProjectUser, ProjectEntity)

module.exports = ProjectUser

项目(“单例”但不是真的)

'use strict'

var ProjectClient = require('./lib/client')
var Project = {
init: function(options) {
var self = this
if (self.isInitialized) {
return self
}
Object.setPrototypeOf(Project, new ProjectClient(options))
ProjectClient.call(self)
self.isInitialized = true
}
}

module.exports = Project

客户端

var ProjectUser = require('./user'),
_ = require('lodash')

var ProjectClient = function(options) {
var self = this

// some stuff happens here to check options and init with default values

return self
}

ProjectClient.prototype = {
GET: function() {
return function() {
// async GET request with callback
}
},
PUT: function() {
return function() {
// async PUT request with callback
}
}
}

module.exports = ProjectClient

最佳答案

因此,正如您正确推断的那样,循环依赖存在问题。您的 Entity 模块需要 Project 模块需要 Client 模块需要 User 模块需要 实体模块。

您可以采取一些措施,但这取决于您的起点。如果您首先需要 Project 模块,那么它应该使用提供的代码,因为 Entity 模块不会对 Project 模块执行任何操作。该模块没有导出任何内容,因此它只是一个空对象。再一次,该模块上的任何错误源都与该模块内部依赖的任何导出对象相关。因此,如果您需要 Entity 中带有 init 的对象,那么就会出现问题。

您可以在初始化依赖链之前导出一些方法/函数,这将使它们在那时可用。以NodeJS文档为例:

a.js

console.log('a starting');
exports.done = false;
var b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');

b.js

console.log('b starting');
exports.done = false;
var a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');

main.js

console.log('main starting');
var a = require('./a.js');
var b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);

因此,main.js 是起点。它需要 a.js 立即导出一个 done 属性,然后需要 b.jsb.js 还导出一个 done 属性。下一行需要 a.js ,它不会再次加载 a.js 但返回到目前为止导出的属性(包括 done 属性).此时,a 尚未完成,但它已设法为 b 提供足够的资源以继续工作。它的下一行(在 b.js 上)将打印导出的属性(a.done,它是 false),然后将导出的属性 done 重置为 true。我们回到 require('b.js') 行中的 a.jsb.js 现在已完全加载,其余部分很容易解释。

输出是:

main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true

Here's这个例子,以防你想阅读官方文档。

好吧,重点是……你能做什么?

可以在初始化依赖循环之前导出一些东西,只要您实际上不需要这些依赖即可。例如,您可以:

a.js

exports.func = function(){ console.log('Hello world'); }
var b = require('./b.js');
console.log('a done');

b.js

var a = require('./a.js');
a.func(); //i'm still incomplete but i got func!
console.log('b done');

你不能:

a.js

b.func(); //b isn't even an object yet.
var b = require('./b.js');
console.log('a done');

b.js

exports.func = function(){ console.log('hello world'); }
var a = require('./a.js');
a.func();
console.log('b done');

但是,如果您的 a.js 模块只导出函数,那么只要这些函数没有在其他地方被调用,就没有真正的问题:

a.js

exports.func = function(){ b.func(); }
var b = require('./b.js');
console.log('a done');

b.js

exports.func = function(){ console.log('hello world'); }
var a = require('./a.js');
console.log('b done');

您正在导出一个使用b 的函数,该函数此时不需要知道b,仅当它被调用时才需要知道。所以两个模块都被正确加载。如果您只是导出函数,那么之后声明依赖项没有问题。

所以你可以从你的主要观点中要求 a.jsfunc 将作为 b 引用点正确工作,现在到完整的 b.js 模块。只要不使用在加载依赖项时导出的函数,就可以遵循此模式。

关于javascript - 复杂循环 Node 模块依赖抛出 "TypeError: The super constructor to ' 继承'必须有一个原型(prototype)“,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34597512/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com