Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/458.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在CoffeeScript中使用Node.js require和类解析循环依赖关系_Javascript_Node.js_Coffeescript_Require_Circular Dependency - Fatal编程技术网

Javascript 在CoffeeScript中使用Node.js require和类解析循环依赖关系

Javascript 在CoffeeScript中使用Node.js require和类解析循环依赖关系,javascript,node.js,coffeescript,require,circular-dependency,Javascript,Node.js,Coffeescript,Require,Circular Dependency,我想知道,在使用CoffeeScript类和超级时,是否有一种方法可以习惯性地避免Node.js的require的循环依赖性问题。给定以下简化的CoffeeScript文件: a、 咖啡: C = require './c' B = require './b' class A extends C b: B someMethod: -> super module.exports = A C = require './c' class A extend

我想知道,在使用CoffeeScript类和超级
时,是否有一种方法可以习惯性地避免Node.js的
require
的循环依赖性问题。给定以下简化的CoffeeScript文件:

a、 咖啡:

C = require './c'
B = require './b'

class A extends C
    b: B

    someMethod: ->
        super

module.exports = A
C = require './c'

class A extends C

module.exports = A

B = require './b'
_ = require 'underscore'

_.extend A::,
    b: B

    someMethod: ->
        super
b、 咖啡:

C = require './c'
A = require './a'

class B extends C
    a: A

    someMethod: ->
        super

module.exports = B
这里的第一个明显问题是,a和B之间存在循环依赖关系。无论哪一个首先求值,都将有
{}
作为对另一个的引用。为了在一般情况下解决这个问题,我可能会尝试在每种情况下都执行类似的操作:

a、 咖啡:

C = require './c'
B = require './b'

class A extends C
    b: B

    someMethod: ->
        super

module.exports = A
C = require './c'

class A extends C

module.exports = A

B = require './b'
_ = require 'underscore'

_.extend A::,
    b: B

    someMethod: ->
        super

这是一个小技巧,但似乎是通过移动
模块来解决循环依赖关系的一种常见方法。将
导出到依赖关系B的
require
之前。因为,它随后使用某种类型的
extend
调用(这可能是复制属性和方法的任何方式)到
a.prototype
(又名
A::
)现在的问题是,
super
只能在类声明的上下文中正常工作,因此此代码不会编译。我正在寻找一种方法来保留
super
和其他CoffeScript类功能。

有几种规范的方法来处理此问题。在我看来,没有一种方法特别适用于非常好。(在循环的情况下,Node确实需要支持用导出的对象替换原始上下文中的临时对象。这样做的好处值得做一些丑陋的、骇人的V8技巧,依我看。/rant)

后期施工 您可以有一个“更高级别”的模块,可能是您的库的入口模块,用于执行相互依赖的内容的最终设置:

#
模块.出口=
A类扩展要求“/c”
someMethod:->
超级的
# 
模块.出口=
B类扩展需要“/c”
someMethod:->
超级的
# 
A=需要“./A”
B=需要“/B”
A.b=新的b
B.a=新的a
module.exports=A:A,B:B
很可怕,因为:您现在已经在更高级别的模块中合并了关注点,并从上下文中删除了该设置代码,在上下文中它是有意义的(并且有望保持不变)。这是观察事物不同步的好方法

依赖注入 我们可以通过将设置移回每个单独子模块的关注点,并仅将依赖关系管理删除到更高级别的文件中来改进上述内容。依赖关系将由更高级别的模块获取(无周期),然后根据需要传递:

#
module.exports=({B})->->->
#每一个模块,除了被包裹在一个封闭的
#函数允许我们关闭依赖关系,这是进一步的
#包装在一个允许我们延迟*构造*的函数中。
B=B()
A类扩展要求“/c”
b:新的
someMethod:->
超级的
# 
module.exports=({A})->->->
#每一个模块,除了被包裹在一个封闭的
#函数允许我们关闭依赖关系,这是进一步的
#包装在一个允许我们延迟*构造*的函数中。
A=A()
B类扩展需要“/c”
a:新的
someMethod:->
超级的
# 
A=需要“./A”
B=需要“/B”
#首先,我们关闭每个库的依赖项,
A=A(B)
B=B(A)
#现在我们构造每个的一个副本(每个副本将构造自己的副本)
#副本)
module.exports=A:A(),B:B()
#消费者现在可以得到每个类的构造的、最终的“普通”副本。
可怕是因为:好吧,除了在这个特定场景中绝对丑陋之外(!!?!),您刚刚将解决依赖性问题的任务“推到了消费者身上”。在这种情况下,消费者仍然是您自己,这很好……但是,现在,当您想通过
require('my_library/a')单独公开
a
时,会发生什么
?现在你必须向消费者证明,他们必须用X、Y和Z依赖项参数化子模块……等等等等,等等

不完全类 因此,为了重复上面的内容,我们可以通过直接在类上实现它,从使用者那里抽象出一些依赖性混乱(从而保持关注点的局部性):

#
模块.出口=
A类扩展要求“/c”
@完成=->
需要“.”/b'
@::b=新的b
someMethod:->
超级的
# 
模块.出口=
B类扩展需要“/c”
@完成=->
需要“./a”
@::a=新的a
someMethod:->
超级的
# 
A=需要“./A”
B=需要“/B”
module.exports=A:A.finish(),B:B.finish()
很可怕,因为:不幸的是,这仍然会给API增加一些概念性的开销:“确保在使用
A
之前始终调用
A.finish()
!”可能不会很受用户欢迎。类似地,它可能会导致子模块之间存在模糊的、难以维护的bug依赖关系:现在,A可以使用B的元素…除了依赖于A的B部分(以及哪些部分在开发过程中可能不明显)

解决周期性依赖关系 我无法为您编写这部分内容,但这是唯一一个不可怕的解决方案;如果您向节点程序员提出这个问题,任何节点程序员都会向您提出这一标准解决方案。我提供上述内容是基于堆栈溢出假设的精神,即您知道自己在做什么(并且有很好的理由产生周期性依赖,删除它们将是非常重要的,并且比上面列出的任何缺点对您的项目都更有害)……但在所有现实中,最有可能的情况是,您只需要重新设计架构以避免周期性依赖。(是的,我知道这个建议很糟糕。)


祝你好运!
(=

哇,多全面的答案。谢谢!