[英]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.