Skip to content

Instantly share code, notes, and snippets.

@riyaz-ali
Created March 16, 2017 08:41
Show Gist options
  • Save riyaz-ali/2932b26f693fc1f03af0696d89af59ca to your computer and use it in GitHub Desktop.
Save riyaz-ali/2932b26f693fc1f03af0696d89af59ca to your computer and use it in GitHub Desktop.
A simple Javascript service dependency injection script in es6
let __DI_impl = {
__deps: {}, /* Object containing registered dependencies */
/* register dependency */
register: function(func, args){
let f;
if(!!args)
f = func.bind.apply(func, [func, ...args]);
// ^^^^ ^^^^
// Context for apply & bind
else
f = func;
let inst = new f();
this.__deps[func.name] = inst;
// return func so we can use this as ->
// export default DI.register(Blah) or
// export default DI.inject([Blah]).into(BlahBlah, true /* to register BlahBlah as well */)
return func;
},
/* inject dependency */
inject: function(deps){
let args = []; // Array of resolved dependencies
deps.forEach((val) => {
// sometimes name was undefined without val.constructor.name, so I added it here
// this worked somehow ... could somebody explain why :D
let name = val.name || val.constructor.name;
if(this.__deps[name])
args.push(this.__deps[name]);
else
throw new Error(`Unresolved dependency: ${val.name}`);
});
let that = this; // capture this
return {
into: function(func, register){
if(!!register){
// resolve, inject and register this as well
return that.register(func, args);
} else {
// just resolve and inject
// returning a function here because I was using this in React component ;P
// can change accroding to need...
return function(){
let arg = [].slice.call(arguments, 0, 1);
arg = arg.concat(args)
return new (func.bind.apply(func, [func, ...arg]));
}
}
},
// just for debugging
dump: function(){
console.log(args);
}
}
}
};
// Shadow the implementation
export default {
register: __DI_impl.register.bind(__DI_impl),
inject : __DI_impl.inject.bind(__DI_impl)
};
import DI from "./DI"
// class A
class A {
constructor(){
console.log("A");
}
hello(){
console.log("Hello from A");
}
}
// register A
DI.register(A);
// class B depends on A
class B {
constructor(aInst){
this.a = aInst;
}
callHelloInA(){
this.a.hello();
}
}
// inject A and register B
DI.inject([A]).into(B, true);
// Main Class depends on B
class Main {
constructor(bInst){
this.b = bInst;
// call a function in B
this.b.callHelloInA();
// will log Hello from A
}
}
// Inject B
DI.inject([B]).into(Main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment