I'm currently developing a new web application.
This is the first time I'm using requirejs with AMD modules.
It's not that easy to get used to that new paradigm that there are - as I understand it - no variables in the global namespace.
In previous web applications I always had one variable in the global namespace which I could use to share several resources across different modules.
Now with requirejs AMD modules, I use backbone.js and jquery (both amd versions - jquery 1.7.1 and backbone.js 0.5.3-optamd3).
Somewhere in my application I fetch a backbone.js module from the server (user object). I would like to have access to this module from different AMD modules. I also want to have an application wide event object.
Could you tell me: what is the right way in requirejs AMD to share resources across different modules?
I found a solution myself.
Thank you, IntoTheVoid, for your answer, but I was hoping for an AMD-like solution. This means, not again, "polluting" the global namespace.
There were 2 keys to my solution:
"https://github.com/addyosmani/backbone-aura" from Addy Osmani and "https://github.com/amdjs/amdjs-api/wiki/AMD" the The Asynchronous Module Definition (AMD) API specification.
The spec says: "If the factory is a function it should only be executed once."
So, if an amd module is specified multiple times as a dependency in an web application, the dependency is not only NOT LOADED MULTIPLE TIMES, it is also NOT EXECUTED MULTIPLE TIMES, and this is the new thing to me. It is only executed once and the return value of the factory function is kept. Each dependency with the same path has the same object. And this changes everything.
So, you simply define the following amd module:
define([], function() {
var app_registry = {};
app_registry.global_event_obj = _.extend({}, Backbone.Events);
app_registry.models = {};
return app_registry;
});
Now, in those modules where you want to share resources, you declare this app_registry module as dependency and write in one:
define(['jquery','underscore','backbone','app_registry'],
function ($, _, Backbone, app_registry){
var firstView = Backbone.View.extend({
initialize: function() {
_.bindAll (this, 'methodOne');
this.model.bind ('change', this.methodOne);
this.model.fetch();
},
methodOne: function() {
app_registry.models.abc = this.model;
}
...
and in the other:
define(['jquery','underscore','backbone','app_registry'],
function ($, _, Backbone, app_registry){
var secondView = Backbone.View.extend({
initialize: function() {
_.bindAll (this, 'methodTwo');
app_registry.global_event_obj.bind ('special', this.methodTwo);
},
methodTwo: function() {
app_registry. ...
}
...
To answer your question as to how to provide an application wide event object, you can create an amd module called globalContext and instantiate it in the main.js.
Thereafter you can attach settings to the globalContext and use the global context to create subcomponents etc.
//main.js file
require([ "./global-context" ], function( GlobalContext) {
new GlobalContext();
});
In the global-context.js file we can then perform tasks such as loading child modules
define(["Boiler", "./settings", "./modules/modules"],
function (Boiler, settings, modules) {
var GlobalContext = function () {
//here we use a template javascript class called Boiler.Context
var globalContext = new Boiler.Context("GlobalModule");
//add settings to the context which can be obtained globally throughout the application
globalContext.addSettings(settings);
//here we load the sub modules of the global context
globalContext.loadChildModules(modules);
};
This is what we have implemented in BoilerplateJS, a reference architecture for large scale javascript product development.
You can use the initialize pattern to inject any value into a requirejs module (aka 'dependency injection').
Do a require call anywhere in your code:
var MyBackboneModule;
MyBackboneModule = someWayToGetAReferenceToIt();
require("module", function(Module) {
Module.initialize(MyBackboneModule);
});
With module.js file defined as
define([], function(){
var BackboneModuleDoingThisAndThat;
function initialize(pBackboneModule) {
BackboneModuleDoingThisAndThat = pBackboneModule ;
};
function doSomething() {
var x = BackboneModuleDoingThisAndThat.computeThis(42);
};
return {
initialize: initialize
};
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With