🌌 a small decoupled, event-driven architectural framework
ākāśe (sanskrit for “in the sky”/“to the sky”) is a small decoupled, event-driven architecture framework.
It is based on Nicholas Zakas Scalable Javascript Application Architecture and RequireJS and AMD.
The concepts of the framework are well represented by the two presentations linked above.
Basically everything gets sandboxed and everyone is happy. (play with it)
The modules you will have to create are proper AMD modules with this skeleton
define(function(){
'use strict';
return function(sandbox){
//the logic of the module
function doSomething(){
//do something
}
return {
init:function(config){
//the initialization code
sandbox.subscribe('myEventName', doSomething)
},
destroy: function(){
//optional destroy method, useful to remove callbacks from DOM event
}
};
};
});
As in the example, every module has access to the sandbox, which is supposed to be the only external api accessible, but no one forces you not to require a framework (watch out that you are coupling your code with that specific framework, just saying)
define(['jQuery'], function($){
'use strict';
return function(sandbox){
function doSomething(){
//do something
}
return {
init:function(config){
$('#myElm').on('click', doSomething);
}
};
};
});
The sandbox API should be defined/extended by you, the only API available out of the box allows to:
access the module name
sandbox.module
publish an event through the whole architecture
sandbox.publish(eventName, payload)
Parameters:
subscribe to an event
sandbox.subscribe(eventName(s), callback)
Parameters:
namespace your own Api
sandbox.api
Everything gets started in a proper RequireJS way
<script data-main="main.js" src="/assets/javascripts/require.js"></script>
The main file should require ākāśe core lib in order to take advantage of the framework
require(['akase'], function(core) {
//[...]
});
the core exposes 3 methods in order to:
load and initialize a module
start(moduleId, options)
Parameters:
akase.config.moduleName
is available and will extend the inlined config with it. Useful if you need dynamic data from the page (example below).stop and undefine the module (next start will reload the resource)
stop(moduleId)
Parameters:
broadcast events into the architecture, it works as the sandbox.publish
notify(event, payload)
Parameters:
example of a proper main.js
require(['akase', 'module1', 'module2', 'module3', 'module4'], function(core) {
var audio = document.createElement("audio"),
canPlayMP3 = (typeof audio.canPlayType === "function" && audio.canPlayType("audio/mpeg") !== "");
core.start("module1", {
config: {
hasMp3Support: canPlayMP3
}
});
core.start("module2");
core.start("module3", { event: "audio:stop" });
});
Wait for config (added in v1.1.0)
core.start("module4", { waitForConfig: true})
In this case the core would wait for a global configuration on the global akase
object before starting module4
.
Very useful if you need to pass dynamic data from the page rendered by the server to the application.
akase.config['module4'] = {
productId: 'AGS1241S'
}
The core is re-checking for 5 seconds and then give up, no error thrown.
In order to have RequireJS proper loading modules you’d read RequireJS documentation to configure the paths
To all the guys that helped me creating ākāśe with their inspiration or making me copy their ideas: Marco Pracucci, Rocco Zanni, Luca Lischetti, Rocco Curcio