Angular 2 - Dependency Injection and Barreling

2019-03-27 00:42发布

I've had a issue with Dependency Injection when importing a service from a barrel (https://angular.io/docs/ts/latest/glossary.html#!#barrel).

The issue I've faced is this:

Using the Angular guidelines, in the app there's a core barrel and then a barrel for every folder, these are achieved by having an index.ts in each folder. The core index.ts references everything from each folder and in turn each folder references the specific files.

core index.ts

...
export * from './test/index';

test index.ts

...
export * from './my-service.service';

Code

import { MyService } from '../../core';
...

@Injectable()
export class AuthGuard implements CanActivate {
    isValidSession: boolean = false;
    errorMessage: any;

    constructor(
        private myService: MyService
    ) { }

    canActivate(
        // Not using but worth knowing about
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
    ) {
        return this.myService.doSomething();
    }
}

The above code resulted in the following error:

Uncaught Cannot resolve all parameters for 'AuthGuard'(undefined). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthGuard' is decorated with Injectable.

Looking at the code I did not find any issue with missing @Injectable annotations. In fact the same service was being used in other components and was imported using the core index.ts.

An article I found suggested that @Inject in the constructor should be used because sometimes when TypeScript is converted to JavaScript the metadata is not created. This did not solve the issue in my case. After trying several things I simply tried changing the import to get the service like below, and the error was not thrown.

Successful importation:

import { MyService } from '../../core/test/my-service.service';

or

import { MyService } from '../../core/test';

I'm not sure if there's an issue in the index.ts files in my application or maybe the file structure itself is wrong, but from what I can see they're working fine. Would like to know why this particular import is making a difference.

2条回答
\"骚年 ilove
2楼-- · 2019-03-27 01:18

I've had the exact same problem and Günter is right: The order of exports in the barrel does seem to matter.

In my case I had in my barrel:

export * from 'my.component'
export * from 'my.service'

which resulted in the same error that you saw. Putting the service before the component that's using it solved the problem:

export * from 'my.service'
export * from 'my.component'

I didn't find any documentation about this but I find this behavior definitely less than ideal because

  • it's implicit
  • it's not documented
  • the error-message doesn't give you any hints on how to fix it
查看更多
趁早两清
3楼-- · 2019-03-27 01:20

The order does matter as stated above! Not sure if it's a bug or not but anyway...

So, it looks to me that classes decorated with metadata should be at the top of the index.ts If one of them injects another, the "another" should be above the "one".

查看更多
登录 后发表回答