JavaScript Dependency Injection

后端 未结 12 1625
天涯浪人
天涯浪人 2020-12-22 16:51

I am new at JavaScript. I wonder how dependency injection is being implemented in JavaScript? I searched the internet but couldn\'t find anything.

12条回答
  •  佛祖请我去吃肉
    2020-12-22 17:40

    For me yusufaytas answer was exactly what I needed! The only missing features were:

    1. Getting a dependency with custom parameters.
    2. Registering dependencies using callbacks.

    I wanted to have the ability to do something like this:

    Injector.register('someDependency', function () {
            return new ConcreteDependency();
    });
    
    function SomeViewModel(userId, someDependency) {
        this.userId = userId;
        this.someDependency = someDependency;
    }
    
    var myVm = Injector.get(SomeViewModel, { "userId": "1234" });
    

    So I ended up with the following code:

    var Injector = {
    
        factories = {},        
        singletons = {},
    
        register: function (key, factory) {
            this.factories[key] = factory;
        },
    
        registerSingle: function (key, instance) {
            this.singletons[key] = instance;
        },
    
        get: function (CTor, params) {            
    
            var dependencies = this.resolveDependencies(CTor, params);
    
            // a workaround to allow calling a constructor through .apply
            // see https://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
            function MiddlemanCTor() {
                CTor.apply(this, dependencies);
            }
    
            MiddlemanCTor.prototype = CTor.prototype;
    
            return new MiddlemanCTor();
        },
    
        resolveDependencies: function(CTor, params) {
            params = params || {};
            var args = this.getArguments(CTor);
    
            var dependencies = [];
            for (var i = 0; i < args.length; i++) {
                var paramName = args[i];
                var factory = this.factories[paramName];
    
                // resolve dependency using:
                // 1. parameters supplied by caller
                // 2. registered factories
                // 3. registered singletons
                var dependency = params[paramName] ||
                    (typeof factory === "function" ? factory() : undefined) ||
                    this.singletons[paramName];
    
                dependencies.push(dependency);
            }
            return dependencies;
        }
    
        getArguments: func(func) {
            // Regex from require.js
            var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
            var args = func.toString().match(FN_ARGS)[1].split(',').map(function (str) {
                return str.trim();
            });
            return args;
        }
    };
    

    Update - 21.5.2018

    I've been using this solution for a few years now. As I moved my code base to TypeScript the solution evolved with it to support both TypeScript and JavaScript. After quite a while that the code was running in production I recently (two days ago) published a library based on this solution. Feel free to check it out, open issues, etc.

    peppermint-di

提交回复
热议问题