FatalCatharsis
FatalCatharsis

Reputation: 3567

angularjs: invoke creates new services

I have a big list of a services and controllers that are created when the website first loads and then I call angular.bootstrap. Then, later I would like to run some arbitrary code that can be dependency injected. The way I do this is by creating a function, specifying it's dependencies with annotations, getting the injector for the module I was using, and then calling invoke on that function.

I use requirejs to load this plugin and any other plugin so that is what is being returned out of the module. the code looks like this

define [
    'scripts/inherits/basePlugin'
] , (BasePlugin) ->
    # The explicit block lists the angular services/factories you need
    # all game logic/entity classes go inside this block
    explicit = (Options, Renderer) ->
        class Checkers extends BasePlugin.Plugin
            constructor: () ->
                super()
                @checkersOptions = [
                    [
                        "checkbox",
                        "test checkbox",
                        false
                    ],
                    [
                        "slider",
                        "test slider",
                        0, 3, 1
                    ],
                    [
                        "textbox",
                        "test textbox",
                        "this is some text"
                    ],
                    [
                        "dropdown",
                        "test dropdown",
                        ["blah", "blah2", "blah3"],
                        "blah2"
                    ]
                ]
                Options.addPage "Checkers", @checkersOptions

            selectEntities: (renderer, turn, x, y) ->

            verifyEntities:(renderer, turn, selection) ->

            getName: () -> 'Checkers'

            predraw: (turn, dt, renderer) ->

            postdraw: (turn, dt, renderer) ->

            resize: (renderer) ->

            loadGame: (@gamedata, renderer) ->

            getSexpScheme: () -> null

        return Checkers

    # the dependencies are manually injected here
    explicit.$inject = ['Options', 'Renderer']
    $injector = angular.injector(['webvisApp'])

    # the constructor function for the main checkers object is returned here
    return $injector.invoke(explicit)

Now at the end, i'm trying to return the class prototype for 'Checkers' here that has access to angular services 'Options' and 'Renderer'. At the end when I call invoke, it runs without complaint but for some reason the two services are re-instantiated, as in the constructors for those two services are invoked again, obliterating any data that they previously had. Why does invoke cause these services to be recreated?

EDIT: SOLUTION: Turns out the injector function creates new injectors instead of using the one in your module. my solution was this:

# make your module
webvisApp = angular.module 'webvisApp', [
    'ngCookies'
    'ngSanitize'
    'ngRoute'
    'ui.bootstrap'
]

# attach injector to publicly accessible member
webvisApp.run ($injector) ->
    webvisApp.injector = $injector

# create your controllers and services

# bootstrap the application
angular.bootstrap document, ['webvisApp']

Then to invoke some function with dependencies:

needsDependencies = (Renderer, Options) ->
   #do stuff

needsDependencies.$inject = ['Renderer', 'Options']
webvisApp = angular.module('webvisApp')
webvisApp.injector.invoke needsDependencies

Upvotes: 0

Views: 33

Answers (1)

Estus Flask
Estus Flask

Reputation: 222780

You're creating new injector instance with angular.injector, and it differs from the one that you've got with angular.bootstrap elsewhere. Each of these injector instances creates its own service instances.

I'm not quite sure about application architecture, but I guess that you have to provide an injector from bootstrapped application to all modules.

Upvotes: 1

Related Questions