[英]TypeError: Super expression must either be null or a function _inherits in react native
[英]Complex circular Node module dependency throwing “TypeError: The super constructor to 'inherits' must have a prototype”
我有一个复杂的Node SDK项目,它使用一些类继承来尝试和static-ify Javascript。 我正在使用Node的模块缓存行为为SDK( Project
类, ProjectClient
的共享实例)创建类似单一的行为。 对于init,它看起来像这样:
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)
故障导致我这之中涉及到util.inherits(ProjectUser, ProjectEntity)
的User
,因为如果我注释掉,我得到这个:
Uncaught TypeError: ProjectEntity is not a function
inherits
什么? 为什么它认为Entity
没有原型? 我最好的猜测是,它与我在其他模块中递归嵌套模块这一事实有关(糟糕,我知道),但我甚至尝试过在各种类中做这样的事情,但无济于事:
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
模块,该模块需要需要Entity
模块的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.js
b.js
还出口一个done
财产。 下一行需要a.js
,它不会再次加载a.js
但返回到目前为止的导出属性(包括done
属性)。 在这一点上, a
是不完整的,但它设法给b
足以继续工作。 它的下一行(上b.js
)将打印输出特性(a.done,这是假的),然后重新导出属性done
设置为true。 我们回到a.js
的require('b.js')
线。 b.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
这是一个例子,以防您想阅读官方文档。
是的,所以重点......你能做什么?
只要您实际上不需要这些依赖项,就可以在初始化依赖项循环之前导出一些内容。 例如,你可以:
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.js
,并且func
将正常工作,因为b
参考点现在指向完整的b.js
模块。 只要在加载依赖项时不使用导出的函数,就可以遵循此模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.