11

I've recently created a new project using AngularJS and ES6. This is my first ES6 project, and I'm very satisfied with it's import statements. Previously I had to use AngularJS dependancy injection in order to use different services in my applications' logic. Now I can easily import different services using ES6 import. The question is that am I allowed to write non-angular services and import them using import, or I must write them in angular service (or factory) format, and use dependency injection to import?

5
  • Dependency injection and imports are not even remotely related. You will use both. Commented May 9, 2017 at 8:08
  • 3
    Yes, I use both. But my question is about requiring a service in a controller. I can write angular service and inject it into controller, or I can write a normal JS class or function and import it to use in controller. I'm asking if it is an anti-pattern in AngularJS to use import instead of AngularJS DI. @zeroflagL Commented May 9, 2017 at 9:35
  • 6
    I think it's a perfectly valid question. I too am searching for an answer to this. Commented May 17, 2017 at 3:28
  • Possible duplicate of Angular 2 when to use DI, provider or pure import? Commented May 18, 2017 at 15:30
  • I'm using webpack with angular 1.6.x and I quit using angular DI in favor of ES6 imports. When I need some ng services like $http, $q and so on I inject them directly using the angular.injector function. Dunno if it isn't a best practice or not, but it works quite nicely. Commented Aug 31, 2017 at 21:08

2 Answers 2

5

First of all, Angular dependency injection and ES6 import are 2 different concepts.

Angular dependency injection is a way to provide components with their dependencies instead of hard coding them within the component. This relieves a component from locating the dependency and makes dependencies configurable.

ES6 import is a javascript feature which is used to import bindings which are exported by another module.

You can import a module, which can be your service class and add it as an angular service. If you are writing a 'non-angular' service, just make sure it is exportable ES6 class. You cannot directly use an ES6 class as a dependency because angular needs to angular-ify it before DI.

my-service.service.js

export default class MyService {
  constructor() {
    this.items = [''];
  }

  getItem() {
    return this.items;
  }
}

MyService.$inject = ['SomeOtherService'];

in index.js

import angular from 'angular';
import MyService from './my-service.service';

angular.module('myApp')
  .service('MyService', MyService);

This is one way which ES6 can work with AngularJS dependency injection.

Sign up to request clarification or add additional context in comments.

Comments

3

Personally, I eventually have started to only use DI to inject internal services like $http AND singleton application (business-logic) services, which are few.

If I need class, that I want to instantiate (new Something(...)) by myself, then I use es6 module import syntax and pure es6 classes. And across my application these type of classes are majority.

That's it, works perfectly fine. I must say that I've come to this workflow because IDE autocompletion didn't work properly with DI approach, and it started to annoy me very much. Now I enjoy absolutely awesome, correct and superfast autocompletion.

Angularjs dependencies (particularly factories) were a life-savers in before-es6-imports era, because it isolated namespaces for you. Now es6 modules do this. You still benefit from DI, though, because it is only convenient way to use Angular's internal services (e.g. $http) and it is convenient way to instantiate singleton classes (with .service(...)).

UPD. If you want to use angularjs dependencies in your classes outside angularjs, you may use this:

$http = injector('$http')

Injector function comes from here:

// injector.js
let cache = {}

/**
 * Use example:
 * import injector from 'injector.js'
 * $http = injector('$http')
 *
 * @param dependency {string}
 */

export function injector (dependency) {

  return cache.hasOwnProperty(dependency)
    ? cache[dependency]
    : cache[dependency] = angular.element(document).injector().get(dependency)
}

Important! injector() function must run only after document is ready. Usually this is the case, but if not, you will get error "Cannot read property 'get' of undefined" in injector (injector.js). Solution is simply injecting after document is ready:

import { injector } from '../injector.js'

let $http;

angular.element(document).ready(() => {
  $http = injector('$http')
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.