3

I want to write some kind of Broadcast mechanism to dynamically create and use EventEmitters in my user context. To do so I inject the an EmitterService

@Injectable()
export class BroadcastService implements OnInit {
    private _emitters: { [channel: string]: EventEmitter<any> } = {};    
    constructor() {}    
    get(channel: string): EventEmitter<any> {
        if (!this._emitters[channel]) { 
            this._emitters[channel] = new EventEmitter();
        }
        return this._emitters[channel];
    }    
    ngOnInit() { }    
}

My components structure looks like this:

                [root]
                 |  |
           [comp-a][comp-b]

In my root component I inject the BroadcastService to make sure every sub-component uses the same Broadcast Channels. In addition other services like an AuthService are injected (in the root too, that's basically my user context)

@Component({
    provider: [BroadcastService, AuthService]
})

The AuthService (and others) are using the BroadcastService for emit events:

@Injectable()
export class AuthService extends BaseService {      
constructor(
        http: Http,
        @Inject(BroadcastService) private emitterService: BroadcastService)
    {              
        super(http);                 
    }
    ...
    // Example usage of Broadcast
    login(username: string, password: string) {
        // do the login, when successfully:
        this.emitterService.get("online").emit(true);
    }
}

The error I get: EXCEPTION: Cannot resolve all parameters for 'AuthService'(Http, undefined @Inject(undefined)). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthService' is decorated with Injectable.

What I tried:

  1. Putting another root component on top the the current root component to inject the BroadcastService there, same result
  2. Adding/Removing the @Inject to the constructor parameter, no changes
  3. Begging and crying, didn't help

The strangest part is, that this works with one of my other services and doesn't with the rest of them (well, I didn't try all, but those I tried didn't work). Do you have any clues what the problem could be? Or is this maybe just a bug (I'm using angular2 in 2.0.0-beta.2)

3
  • Did you add HTTP_PROVIDERS to bootstrap(AppComponent, [...])? @Inject(BroadcastService) is redundant AFAIK. Commented Jan 31, 2016 at 17:44
  • yes. and I really have no idea, what the problem could be anymore Commented Jan 31, 2016 at 17:49
  • I guess it's the order of the classes in the source file. Are AuthService and BroadcastService in the same file? Change the order of these two classes or use forwardRef Commented Jan 31, 2016 at 17:51

1 Answer 1

5

Seems like a forwardRef is required

@Injectable()
export class AuthService extends BaseService {      
constructor(
        http: Http,
        @Inject(forwardRef(()  => BroadcastService)) private emitterService: BroadcastService)
    {              
        super(http);                 
    }
    ...
    // Example usage of Broadcast
    login(username: string, password: string) {
        // do the login, when successfully:
        this.emitterService.get("online").emit(true);
    }
}

could also (or instead of) be necessary in

@Component({
    provider: [BroadcastService, AuthService]
})

depending on how you code is organized. This is not necessary when each class is defined in its own file.

See also Angular 2 error:

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

2 Comments

Great, thanks. Do you have a nice guide to understand what exactly is going on. I know what a forward reference in general is and why it is needed. But this special case is still a bit of a misteria for me
Classes are not hoisted and therefore not yet known where they are used as type. With forwardRef the resolution of the type is delayed to later when the whole file content is known. See also blog.thoughtram.io/angular/2015/09/03/… and angular.io/docs/ts/latest/api/core/forwardRef-function.html

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.