Skip to content Skip to sidebar Skip to footer

Ember.js Application.inject Circular Dependencies

Hi, I'm about 2 weeks into building my application with ember.js, and the time has come to pull together my project layout into its final shape. To that end, I started looking into

Solution 1:

You definitely have a circular dependency, and if you were using a different language I'd tell you to use the inversion of control pattern, but it's a little difficult using your problem and the container.

Solution 1

If you're fine adding them under a namespace such as manager or something like that then here's a solution (it's tightly coupled, but the code is tightly coupled already, almost enough that they could be together or a mixin on the other).

App.Manager = Ember.Object.extend({
  init: function(){
    // late fake injection
    this.authManager.dataManager = this.dataManager;
    this.dataManager.authManager = this.authManager;
  }
});


App.initializer({
    name: "manager",
    after:['dataManager', 'authManager'],

    initialize: function (container, application) {
        application.register("my:manager", application.Manager);
        application.inject("my:manager", "dataManager", "my:dataManager");
        application.inject("my:manager", "authManager", "my:authManager");
        application.inject("controller", "manager", "my:manager");
        application.inject("route", "manager", "my:manager");
    }
});

App.initializer({
    name: "dataManager",

    initialize: function (container, application) {
        application.register("my:dataManager", application.DataManager);
    }
});

App.initializer({
    name: "authManager",

    initialize: function (container, application) {
        application.register("my:authManager", application.AuthManager);
    }
});

And an example:

http://emberjs.jsbin.com/mopaquko/2/edit

Solution 2

On another note, this creates a new instance on each route/controller. If you only need one instance. You can do it like so, much easier and doesn't need the namespace.

App.initializer({
    name: "joinManagers",
    after:['dataManager', 'authManager'],

    initialize: function (container, application) {
      var dataManager = container.lookup('my:dataManager'),
          authManager = container.lookup('my:authManager');
        
        authManager.dataManager = dataManager;
        dataManager.authManager = authManager;
      
        application.register("my:jointDataManager", dataManager, {instantiate:false});
        application.register("my:jointAuthManager", authManager, {instantiate:false});
        application.inject("controller", "dataManager", "my:jointDataManager");
        application.inject("controller", "authManager", "my:jointAuthManager");
        application.inject("route", "dataManager", "my:jointDataManager");
        application.inject("route", "authManager", "my:jointAuthManager");
    }
});


App.initializer({
    name: "dataManager",

    initialize: function (container, application) {
        application.register("my:dataManager", application.DataManager);
    }
});

App.initializer({
    name: "authManager",

    initialize: function (container, application) {
        application.register("my:authManager", application.AuthManager);
    }
});

http://emberjs.jsbin.com/mopaquko/3/edit

Solution 3

As was pointed out, Ember's container create's singletons by default, you can eagerly create the copies then allow ember to still resolve based on the original namespace.

App.initializer({
    name: "joinManagers",
    after:['dataManager', 'authManager'],

    initialize: function (container, application) {
      var dataManager = container.lookup('my:dataManager'),
          authManager = container.lookup('my:authManager');

        authManager.dataManager = dataManager;
        dataManager.authManager = authManager;

        application.inject("controller", "dataManager", "my:dataManager");
        application.inject("controller", "authManager", "my:authManager");
        application.inject("route", "dataManager", "my:dataManager");
        application.inject("route", "authManager", "my:authManager");
    }
});


App.initializer({
    name: "dataManager",

    initialize: function (container, application) {
        application.register("my:dataManager", application.DataManager);
    }
});

App.initializer({
    name: "authManager",

    initialize: function (container, application) {
        application.register("my:authManager", application.AuthManager);
    }
});

http://emberjs.jsbin.com/mopaquko/7/edit


Post a Comment for "Ember.js Application.inject Circular Dependencies"