Naming Prosecution Mitigator
    Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »

    di-litepublic

    build status

    di-lite.js

    di-lite is designed to act as a minimalistic dependency injection container in Javascript. It has no dependency on any other framework such as CommonJs or RequireJs in contrary to some of other more heavy weight DI container implementation on the web.

    Use Cases

    di-lite was initially extracted from a Backbone.js based application. In this application, RequireJs was used to wire dependencies at module level. Each module could contain multiple views and models. We found using RequireJs to wire every individual view and model is a bit of overkill and verbose, however we still want the inversion of control to keep our code nicely isolated and testable. That's the reason behind the creation of this lightweight container implementation - to provide dependencies injection at sub-modular level.

    That being said di-lite is designed to be used standalone there is no dependency on Backbone or RequireJs. Its a fully functional dependency injection container by itself while extremely lightweight and works well both in browser or node.

    Install with npm

    npm install di-lite

    Install without npm

    Download

    How-to Guide

    Basic Wiring

    var A = function(){
        ...
        this.dependencies = "b, c";
        ...
    };
    var B = function(){
        ...
        this.dependencies = "c";
        ...
    };
    var C = funciton(){...};
     
    // create di context
    var ctx = di.createContext();
     
    // register a class with an unique name
    ctx.register("a", A);
    ctx.register("b", B);
    ctx.register("c", C);
     
    // initialize di container so all singleton(default) objects will be wired at this stage
    ctx.initialize();
     
    var instanceOfA = ctx.get("a");
    instaceOfA.b === ctx.get("b"); // true
    instaceOfA.c === ctx.get("c"); // true
     
    var instanceOfB = ctx.get("b");
    instanceOfB.c === ctx.get("c"); // true

    Wiring with Assignment

    By default dependencies are wired using their registered name respectively, however you can override this behavior by including an explicit assignment in dependency definition. You can also mix both explicit and implicit assignment in dependency definition.

    var A = function(){
        ...
        this.dependencies = "bee=b, c"; // mix explicit and implicit assignment
        ...
    };
     
    ctx.initialize();
     
    var instanceOfA = ctx.get("a");
    instaceOfA.bee === ctx.get("b"); // true - explicit assignment
    instaceOfA.c === ctx.get("c"); // true - implicit assignment

    Passive Dependency Resolution

    di-lite container resolves dependency passively on demand when get() method is invoked. It only tries to resolve dependency for this particular object thus only traverse its sub-dependency-tree. initialize() call does resolve all dependencies for all registered objects however it is actually optional (though recommended to guarantee).

    ctx.register("a", A);
    ctx.get("a"); // this triggers the dependency resolution for "a" alone
    ctx.initialize(); // this triggers the dependency resolution for everyone registered

    Singleton By Default

    All objects created and managed by di-lite.js container are by default singleton.

    ctx.get("a") === ctx.get("a"); // true

    Prototype Strategy

    If you want container to create a new instance of your class each time you invoke get method then you need to configure your registration with di.strategy.proto cache strategy.

    ctx.register("prototype", A).strategy(di.strategy.proto);
    ctx.get("prototype") === ctx.get("prototype"); // false
    ctx.create("prototype", 100); // create can be used if you want to explicitly pass in a new parameter

    Passing Constructor Arguments

    You can pass arguments to constructor function by using the additional parameter in register call.

    ctx.register("str", String, "hello world"); // signle simple argument
    ctx.register("profileView", ProfileView, {el: "#profile_div"}); // signle object literal argument
    ctx.register("array", Array, ["Saab","Volvo","BMW"]); // multiple argument is passed in using an array

    Cyclical Dependency

    di-lite.js container supports solution of cyclical dependencies, so the following dependency relationship is valid.

    var A = function(){
        ...
        this.dependencies = "b";
        ...
    };
    var B = function(){
        ...
        this.dependencies = "a";
        ...
    };
     
    ctx.register("a", A);
    ctx.register("b", B);
     
    ctx.initialize();
     
    ctx.get("a").b === ctx.get("b"); // true
    ctx.get("b").a === ctx.get("a"); // true
    ctx.get("a").b.a === ctx.get("a"); // true
    ctx.get("b").a.b === ctx.get("b"); // true

    Functional Object

    What if your are using functional object pattern and do not have a constructor function for your object? di-lite.js fully supports functional object pattern since we believe this is the best way to create javascript object anyway.

    var FuncObject = function(spec){
        var that = {};
        ...
        return that;
    };
     
    ctx.register("funcObjSingleton", FuncObject, spec).factory(di.factory.func);
     
    // function chaining can be used to customize your object registration
    ctx.register("funcObjProto", FuncObject, spec)
        .strategy(di.strategy.proto)
        .factory(di.factory.func);
     
    ctx.initialize();
     
    ctx.get("funcObjSingleton"); // will return you a signleton instance of FuncObject
    ctx.get("funcObjProto"); // will return you a new instance of FuncObject each time

    Lifecycle Hook

    di-lite container provides a lifecycle hook callback ready if the wired object provide a ready function then the callback will be executed once all dependencies are satisfied.

    var MyView = Backbone.View.extend({
        ...
        dependencies: "otherView, myModel",
        ready: function(){this.render();} // called once all dependencies are satisfied
        ...
    });

    Runtime Dependencies Override

    What if I need to provide different dependencies different instances of the same class?

    ctx.register("a", A)
        .dependencies("bee=b"); // dependencies specified here will take precedence
    ...
    ctx.get("a").bee === ctx.get("b"); // true

    Create Your Own

    Sometimes you just don't have control over the object you want to wire or maybe you need to create the object and initialize before anything else is create or even registered. You can manually insert object into di-lite container and control the whole creation process this way.

    ctx.register("history").object(Backbone.history);
    ...
    ctx.get("history").start(); // you can use it since it is already created and initialized
    ...
    ctx.initialize(); // initialize the rest of the objects

    How to build di-lite locally

    Prerequisite modules

    Make sure the following packages are installed on your machine

    • node.js
    • npm
    • apache ant

    Install dependencies

    di-lite$ npm install

    Build and Test

    di-lite$ ./make

    License

    di-lite is an open source javascript library and licensed under Apache License v2.

    Keywords

    none

    install

    npm i di-lite

    Downloadsweekly downloads

    46

    version

    0.3.3

    license

    none

    repository

    githubgithub

    last publish

    collaborators

    • avatar
    • avatar