Reading the requireJs documentation,
in order to fix the Circular Dependencies, is suggested to use exports
to create an empty object for the module that is
You should be able to use the synchronous version of require()
in your B module to access the "A" module:
// B module
define([
'a',
'exports'
], function (a, exports) {
console.log('A:', a); // A, undefined (as I was expecting)
exports.A = function () {
return require('a');
}
...
});
One option would be not to return the module itself, but a function that instantiates the module (in this example it would a constructor as defined in typescript, at the bottom is the generated js code -note that interfaces do not generate .js code)
File IA.ts
/// <reference path="IB.ts" />
interface IA{
funcA();
_classB : IB;
}
File IB.ts
/// <reference path="IA.ts" />
interface IB{
funcB();
_classA : IA;
}
File ClassA.ts
/// <reference path="IA.ts" />
/// <reference path="IB.ts" />
export class ClassA implements IA
{
_classB : IB = null;
constructor(classB : IB)
{
this._classB = classB;
if (classB){
this._classB._classA = this;
}
return this;
}
funcA(){
console.log('I am ClassA');
}
}
File ClassB.ts
/// <reference path="IA.ts" />
/// <reference path="IB.ts" />
export class ClassB implements IB
{
_classA : IA = null;
constructor(classA : IA)
{
this._classA = classA;
if (classA){
this._classA._classB = this;
}
return this;
}
funcB(){
console.log('I am ClassB');
}
}
File MainTest.ts
/// <reference path="../../def/require.d.ts" />
/// <reference path="IA.ts" />
/// <reference path="IB.ts" />
define(['ClassA', 'ClassB'],
function (classA, classB)
{
var aa : IA = new classA.ClassA();
var bb : IB = new classB.ClassB(aa);
bb.funcB();
aa._classB.funcB();
bb._classA.funcA();
aa.funcA();
});
And the generated js code:
File ClassA.js
define(["require", "exports"], function(require, exports) {
var ClassA = (function () {
function ClassA(classB) {
this._classB = null;
this._classB = classB;
if (classB) {
this._classB._classA = this;
}
return this;
}
ClassA.prototype.funcA = function () {
console.log('I am ClassA');
};
return ClassA;
})();
exports.ClassA = ClassA;
});
File ClassB.js
define(["require", "exports"], function(require, exports) {
var ClassB = (function () {
function ClassB(classA) {
this._classA = null;
this._classA = classA;
if (classA) {
this._classA._classB = this;
}
return this;
}
ClassB.prototype.funcB = function () {
console.log('I am ClassB');
};
return ClassB;
})();
exports.ClassB = ClassB;
});
File MainTest.js
define(['ClassA', 'ClassB'], function (classA, classB) {
var aa = new classA.ClassA();
var bb = new classB.ClassB(aa);
bb.funcB();
aa._classB.funcB();
bb._classA.funcA();
aa.funcA();
});
finally, the output will be:
I am ClassB
I am ClassB
I am ClassA
I am ClassA
I often have circular issues using AMD modules to build an application core that both stands up many modules and contains config or other useful objects for those modules to use.
I did some experimenting today and this seems to work pretty well.
define(['exports', 'underscore', './config', './mediator'],
function (exports, _, Backbone, config, Mediator){
Core = /* ... */
// Publicize a core 'singleton' so that it's dependencies can access it, and so can modules that define it as a dependency themselves.
core = new Core()
exports.core = core //publicize it in a way that supports circularity
return core // And also publicize it normally
}
)
The objects are both '===' equal to each other, so this seems very promising.
EDIT:
The above method doesn't work when optimized. Here's another method that may (untested): https://github.com/requirejs/example-multipage/blob/master/www/js/app/main1.js#L2
define(function (require) {
var $ = require('jquery'),
lib = require('./lib'),
Core;
Core = /* ... */
return new Core()
});