CommonJS singelton模块中的循环依赖

时间:2015-01-20 10:07:15

标签: javascript node.js browserify circular-dependency commonjs

我想知道以下是否可能以及如何:

CommonJS环境,用于节点和/或浏览器的模块(带Browserify)。

每个返回singelton的两个(或更多)模块需要在应用程序的不同部分/模块中可用。他们也应该能够互相呼叫,因此存在循环依赖性案例。我知道有可能通过某种依赖注入,但我想避免一种代码结构,我需要调用类似 this.dependencies.ModuleName 之类的东西来调用另一个seseltons上的方法那些。我希望能够直接在require-statements返回的对象上调用方法。

我意识到两个CommonJS模块直接输出实例化的singelton对象是不可能的(因为循环依赖)。所以我希望可以使用一个通用的代码包装它做一些魔术。类似的东西:

var Magic = require('./magic');

module.exports = Magic.createSingelton({
   // ...
});

Browserify因循环依赖而失败的示例:

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

var a = require('./class-a'),
    b = require('./class-b');

a.printSomething();
b.printSomething();
},{"./class-a":2,"./class-b":3}],2:[function(require,module,exports){

var b = require('./class-b');


var A = function() {};

A.prototype = {
    printSomething: function() {
        document.querySelector('body').innerHTML = document.querySelector('body').innerHTML + 'A got from B: ' + b.getSomething() + '<br />';
    },

    getSomething: function() {
        return 'FROM A';
    }
};

module.exports = new A();
},{"./class-b":3}],3:[function(require,module,exports){

var a = require('./class-a');


var B = function() {};

B.prototype = {
    printSomething: function() {
        document.querySelector('body').innerHTML = document.querySelector('body').innerHTML + 'B got from A: ' + a.getSomething() + '<br />';
    },

    getSomething: function() {
        return 'FROM B';
    }
};

module.exports = new B();
},{"./class-a":2}]},{},[1]);

我知道RefluxJS数据存储正在以这种方式工作。可以从商店外部或从一个商店到另一个商店调用操作。但是,您必须创建操作模块和存储模块。是否需要某种类型的结构,或者如上所述每个singelton可以使用一个模块吗?示例代码表示赞赏。

1 个答案:

答案 0 :(得分:0)

所以在你的情况下,Foo在Bar之前加载,因此Bar可以在加载时使用Foo,但是Foo在加载时不能使用Bar。

我通常做的是创建一个init函数(Foo.init,Bar.init)并在所有资源加载完成后调用所有init函数。在您的示例代码中,这不是必需的,因为您在导出中定义的函数允许包含对尚未加载的资源的引用:只要在加载完成之前未执行这些函数。