I have built an Angular application which uses lazy loading. Throughout the application if there is a 1:1 relationship between a component and service I have structured my code as below:
@Injectable()
export class ContactFormService {
....stuff...
}
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.scss'],
providers: [ ContactFormService ]
})
export class ContactComponent {
....stuff...
}
As you can see I've directly added the service as one of the providers, rather than using @Injectable({ providedIn: 'root' })
.
At the time I thought it would help any potential issues around using a singleton, should this service be used in a different component and lose that 1:1 relationship.
The side effect that I have noticed is that when writing unit tests I have to add overrideComponent()
to the configuration
I have to do this (NOTE: I have to override the provided service):
TestBed.configureTestingModule({
declarations: [ContactComponent]
})
.overrideComponent(ContactComponent,
{ set: { providers: [{ provide: ContactFormService, useValue: contactFormServiceSpyObj }] }})
.compileComponents();
Instead of this:
await TestBed.configureTestingModule({
providers: [
{ provide: ContactFormService, useValue: contactFormServiceSpyObj }
],
declarations: [ ContactComponent ]
}).compileComponents();
This has made me wonder am I following a really bad practice? and if so, what circumstances would be suitable to inject a service in the way that I am doing so?
I understand that @Injectable({ providedIn: 'root' })
helps with the tress shaking process when building the application
I see nothing wrong with what you're doing - I also add services to component providers when I want them to be exclusive to the component instance (and possibly the children).
You should remember though to clean up resources on ngOnDestroy
method in the service . (Yes, angular calls ngOnDestroy
on services).
In situations where only one component instance is displayed at once I prefer a different approach to component provider. I use a singleton service provided in root and call an initialization method of the service on the component ngOnInit
. In that method I clean up any resources left over from previous component instance. That comes really handy when I'm using a single application wide state tree and I don't want to generate keys for each component separately.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.