Dependency Injection in AngularJS

Dependency Injection in AngularJS

Here’s a short explanation of how dependency injection works in AngularJS. This time around I’ll talk about how it works internally. In a following post I’ll say more about how to inject dependencies in a practical example.

Finding an Entry Point

Let’s create an example that to find a first approach to dependency injection in AngularJS.

Let’s create a very simple module called “testModule,”

Now let’s add a service and a controller. Let’s call them TestService and TestController, respectively.

We are going to inject TestService into TestController,

Note: If you want to minify/uglify your code, please don’t use the function(TestService) syntax, there are other ways to annotate dependencies.

At this point you should know that there are three ways to annotate the dependencies,

  • Inline Array Annotation
  • $inject Property Annotation
  • Implicit annotation

You can read about the three ways to annotate dependencies in the AngularJS’ official documentation for dependency injection.

Adding a Service or a Controller

Providers in AngularJS are like containers. This is where controllers, services and other things you add to a module are stored.

AngularJS defines different providers for different components of a module. In AngularJS’ GitHub repository we can find a list of the providers in the file loader.js. Looking from line 149 to line 283 you can identify different calls to the invokeLaterAndSetModuleName function. This defines the first parameter as the provider’s name.

So, when you do a call like this,

Internally, this is equivalent to doing a call to,

(Of course, this is the way it works internally, do not use this code.)

When invokeLaterAndSetModuleName is called, you are pushing an element into the invoke queue. If you want more information about this, please review the invokeLaterAndSetModuleName function’s declaration.

What Injects the Dependencies?

By now we have seen how the dependencies are stored. Now, let look at what injects those dependencies.

There is a very important file, injector.js. The file itself has is very well documented and talks about the functions used to inject the dependencies.

There’s also a couple of functions that I think are very important,

  • Annotate function. You can use any of AngularJS’ annotation schemes and it will know which one you are using. There is a function called annote that figures it out.

  • extractArgs function. Probably one of the hardest things for DI is to know the dependencies’ name when we are not specifying the names using an array. In this case, AngularJS has a solution based in the toString() function. When we do this,

    We get the function’s declaration! You can go to a JavaScript editor and try it.

    If you want to know more about how AngularJS gets the dependencies’ name, please review this code.

  • loadModules function. This function loads the modules and runs invokeQueue. There is a lot of code there which you can review by yourself.

    From this point the only thing that AngularJS should do is to find the correct provider for the dependency, instantiate it, and inject it into the function.

Conclusion

To inject a dependency into your code using AngularJS,

  • You declare the function with some parameters to be injected.
  • AngularJS searches for the annotation you used and processes the parameters.
  • AngularJS uses the correct provider and gets an instance of what you want to inject.
  • The instance is applied to the function.

I hope you like this post.

If you have any question or comment please let me know.

Focus Mode

Contact Request

Close

We will call you right away. All information is kept private