简体   繁体   中英

Angular what is the best practice for adding providers to component

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM