当前位置:  开发笔记 > 编程语言 > 正文

复杂的循环节点模块依赖性抛出"TypeError:超级构造函数'继承'必须有一个原型"

如何解决《复杂的循环节点模块依赖性抛出"TypeError:超级构造函数'继承'必须有一个原型"》经验,为你挑选了1个好方法。

我有一个复杂的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类有几种方法,让REST的API调用发生,例如Project.GET(),Project.PUT().在实例化Project"单例" 时,这些工作正常.

我现在正在尝试创建附加的方便方法,例如,Entity利用ProjectClientRESTful操作.Entity.save()Entity.refresh()

当我尝试导入ProjectEntity:

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)in 相关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

MinusFour.. 5

因此,正确地推断出循环依赖性存在问题.您的Entity模块需要Project模块,该Client模块需要User模块,该Entity模块需要模块,该模块需要模块.

你可以做些什么,但这取决于你的出发点.如果您Project首先需要该模块,那么它应该使用提供的代码,因为Entity模块不对模块执行任何操作Project.在该模块上没有导出任何内容,因此它只是一个空对象.然后,该模块上的任何错误源都将与该模块中所依赖的任何导出对象相关.因此,如果您需要init内部对象,Entity则会出现问题.

您可以在初始化依赖关系链之前导出一些方法/函数,这将使它们可用.以NodeJSdocs 为例:

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,为false),然后将导出的属性重置done为true.我们重新回到a.jsrequire('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模块的参考点.只要在加载依赖项时不使用导出的函数,就可以遵循此模式.



1> MinusFour..:

因此,正确地推断出循环依赖性存在问题.您的Entity模块需要Project模块,该Client模块需要User模块,该Entity模块需要模块,该模块需要模块.

你可以做些什么,但这取决于你的出发点.如果您Project首先需要该模块,那么它应该使用提供的代码,因为Entity模块不对模块执行任何操作Project.在该模块上没有导出任何内容,因此它只是一个空对象.然后,该模块上的任何错误源都将与该模块中所依赖的任何导出对象相关.因此,如果您需要init内部对象,Entity则会出现问题.

您可以在初始化依赖关系链之前导出一些方法/函数,这将使它们可用.以NodeJSdocs 为例:

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,为false),然后将导出的属性重置done为true.我们重新回到a.jsrequire('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模块的参考点.只要在加载依赖项时不使用导出的函数,就可以遵循此模式.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有