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 available immediately for reference by other modules.
I try this code but it seems to do not work. What is wrong?
P.S.:
read the ments for seeing the output,
especially the B module inside setTimeout call.
// A module
define([
'b'
], function (b) {
console.log('B:', b); // B, Object
var A = {
boo: 1
};
return A;
});
// B module
define([
'a',
'exports'
], function (a, exports) {
console.log('A:', a); // A, undefined (as I was expecting)
exports.A = function () {
return a;
}
var B = {
bar: 1
};
setTimeout(function () {
console.log('exports.A', exports.A()); // exports.A undefined
// I would like to access the A object
// which is defined in A module
}, 500);
return B;
});
// main.js
(function () {
define([
'a'
], function () {
});
}());
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 available immediately for reference by other modules.
I try this code but it seems to do not work. What is wrong?
P.S.:
read the ments for seeing the output,
especially the B module inside setTimeout call.
// A module
define([
'b'
], function (b) {
console.log('B:', b); // B, Object
var A = {
boo: 1
};
return A;
});
// B module
define([
'a',
'exports'
], function (a, exports) {
console.log('A:', a); // A, undefined (as I was expecting)
exports.A = function () {
return a;
}
var B = {
bar: 1
};
setTimeout(function () {
console.log('exports.A', exports.A()); // exports.A undefined
// I would like to access the A object
// which is defined in A module
}, 500);
return B;
});
// main.js
(function () {
define([
'a'
], function () {
});
}());
Share
Improve this question
edited Jun 29, 2012 at 15:47
Lorraine Bernard
asked Jun 29, 2012 at 15:41
Lorraine BernardLorraine Bernard
13.5k23 gold badges85 silver badges138 bronze badges
4
- I think this might be helpful stackoverflow./questions/4771025/… – Jake Commented Jul 23, 2012 at 5:17
- @lorraine-bernand Did you figure out how to solve this? The link above doesn't give me enough handles to solve it. – donnut Commented Sep 28, 2012 at 8:46
- I wish this was an answered question. I run into this all the time :) – SimplGy Commented Jul 15, 2013 at 23:56
- possible duplicate of How to handle circular dependencies with RequireJS/AMD? – tne Commented Dec 4, 2013 at 12:13
3 Answers
Reset to default 1You 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');
}
...
});
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./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()
});
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