Tech Point Fundamentals

Saturday, December 30, 2023

Angular Interview Questions and Answers - Part 15

Angular Interview Questions and Answers - Part 15

Angular-Interview-Questions-And-Answers

Angular is a popular open-source single-page application design framework and development platform. It is a robust front-end JavaScript framework that is widely used for front-end application development. Nowadays Angular is a very common frontend technology so it is very important for the interview point as well. 

Introduction


This is the Angular Interview Questions and Answers series. Here we will see 200+ Most Frequently Asked Angular Interview Questions. This is the 15th part of the Angular Interview Questions and Answer series.

I will highly recommend to please do visit the following parts before continuing to this part:


Please do visit our YouTube Channel here to watch Interview Questions & Answers and important technology videos.

In this part we will discuss the following Important Angular Interview Questions:

Q171. What is Angular Service? What is the difference between a component and a service?
Q172. What is the difference between Injector, @Injectable, and @Inject in Angular?
Q173. What are the different places to configure the Injectors? How do you configure injectors with providers at different levels?
Q174. What is a provider in Angular DI? 
Q175. What is the scope of a service in Angular?
Q176. How do you restrict a provider scope to a Module only?
Q177. Can you share services using Modules in Angular?
Q178. Why is the service provided in a feature module visible everywhere in the application?
Q179. Why is the service provided in a lazy-loaded module visible only to that module?
Q180. Why does lazy loading always create a child injector?
Q181. How can you check and tell if a NgModule or service was previously loaded?
Q182. What is the difference between the service() and factory() functions in Angular?

Angular Interview Questions and Answers: Part 15


Q171. What is Angular Service? What is the difference between a component and a service?

Angular services provide a way to separate Angular app data and functions that can be used by multiple components in your app. In order to be used by multiple components, a service must be made injectable. Services that are injectable and used by a component become dependencies of that component. The component depends on those services and can't function without them.

A service is any value, function, or feature that an application needs. A service is typically used to accomplish a very narrow purpose such as HTTP communication, sending data to a cloud service, decoding some text, validating data, etc. Angular Services perform tasks that are used by multiple components and avoid rewriting of code.

A service in Angular is a TypeScript class that is used to share data and functionality among many components, directives, or other services in an application. A service is used when a common functionality needs to be provided to various modules. Services allow for greater separation of concerns for your application and better modularity by allowing you to extract common functionality out of components. A service can be written once and injected into all the components that use that service.

Service vs Component:

A Service is different from a component as it is not concerned with HTML or any other kind of UI presentation logic. Normally, a component uses multiple services to accomplish multiple tasks. Services are objects which get instantiated only once during the lifetime of an application. The main objective of a service is to share data and functions with different components of an Angular application.

You can create a service using the ng generate CLI command in the root project directory. 

ng generate service user-service

This command creates a user service for us. In Angular, a service is a class decorated with @Injectable(). A service is defined using a @Injectable decorator. A function defined inside a service can be invoked from any component or directive.

By default, this decorator has a providedIn property, which creates a provider for the service. In this case, providedIn: 'root' specifies that Angular should provide the service in the root injector.

import { Injectable } from '@angular/core';

@Injectable({
    providedIn: 'root'
  })
  export class UserServiceService {
    userName = "TechPoint Fundamentals";    
  }

Services are injected into components via a dependency injection. In order to use a service in Angular:

  • You must first define it by creating a class that implements the service's functionality. 
  • Then, you need to register the service with the Angular injector by adding it to the providers array of the module that wants to use it. 
  • After service registration, you can inject it into any component or other service that needs it.

Each component in Angular has its own isolated scope. But services, are not isolated and can be injected into any other unit in an Angular application like component, module, service, etc. This makes them ideal for sharing data or functionality across the entire app.


Q172. What is the difference between Injector, @Injectable, and @Inject in Angular?

Angular Injector: 

The Angular Injector is the core of the Angular Dependency Injection system.  It is responsible for instantiating the dependency and injecting it into the component or service. Every Angular Injector gets its own copy of Providers. We register all dependencies of the application with the Providers. Every Injector has a Provider associated with it.

The Injector looks for the dependency in the Angular Providers Array using the Injection Token. The Angular providers array returns the Provider, which contains the information about how to create the instance of the dependency. 

@Injectable Decorator:

The Injectable is a decorator, which you need to add to the consumer of the dependency. This decorator tells Angular that it must Inject the constructor arguments via the Angular DI system. It is imported from the angular core.

import { Injectable } from '@angular/core';

@Injectable()
  export class LoggerService {
    log(message:any) {
    console.log(message);
    }
}

The Angular components and directives are already decorated with @Component & @Directive decorators. These decorators also tell Angular to use DI, hence you do not need to add the @Injectable(). The injectable decorator also has the ProvidedIn property using which you can specify how Angular should provide the dependency.

@Injectable({  
  providedIn: 'root'
})
export class SomeService{
}

@Inject Decorator:

The @Inject() is a constructor parameter decorator, which tells angular to Inject the parameter with the dependency provided in the given token. It is a manual way of injecting the dependency. 

export class ProductService{
  constructor(@Inject(LoggerService) private loggerService) {
      this.loggerService.log("Product Service Constructed");
  }
}

The @Inject takes the Injector token as the parameter. The token is used to locate the dependency in the Providers.

Q173. What are the different places to configure the Injectors? or How do you configure injectors with providers at different levels?

We can configure injectors with providers at different levels of your application by setting the metadata value. 

To use any service you must need to register at least one provider for the service. You can register providers in the metadata of the service, module, or component.

The configuration can happen in one of three places:

  1. In the @Injectable() decorator for the service class itself.
  2. In the @NgModule() decorator for a ngModule
  3. In the @Component() decorator for a component

By default, the Angular CLI command ng generate service registers a provider with the root injector for your service by including provider metadata in the @Injectable() decorator. 

When you register a provider with a specific NgModule, the same instance of a service is available to all components in that NgModule. To register at a module level, use the providers property of the @NgModule() decorator.

When you register a provider at the Component level, you get a new instance of the service with each new instance of that component. At the component level, register a service provider in the providers property of the @Component() metadata.

Q174. What is a provider in Angular DI? 

For using any service you must need to register at least one provider for the service. A provider can be part of the service's own metadata, making that service available everywhere, or you can register providers with specific modules or components.

A provider is a configurable service in Angular DI. It is an instruction to the Dependency Injection system that provides information about the way to obtain an instance value for a dependency. A provider is an instruction to the Angular Dependency Injection system on how to obtain a service instance for a dependency. 

It is an object that has a $get() method which is called to create a new instance of a service. A Provider can also contain additional methods and uses $provide in order to register new providers.

You should always provide your service in the root injector unless there is a case where you want the service to be available only if you import a particular @NgModule.

Q175. What is the scope of a service in Angular?

When registering the Services, it is important to understand the scope, in which you want to provide it. Where you register the dependency, it decides the lifetime of the dependency.

Angular basically offers three scopes:

  1. Root Scope or Singleton Scope
  2. Module Scope
  3. Component Scope

If you provide the service in the Module of the root module or any eagerly loaded module, the will be available everywhere in the application. However, the Services provided in the @ngModule of the lazy loaded module are available in that module only.

But if you provide the services in the @Component, @Pipe, or @Directive then they are available only in that component and all of its child components. 

Q176. How do you restrict a provider scope to a Module only?

To use a service we must register the service with one provider and the provider place that decides the scope of the service. It is possible to restrict service provider scope to a specific module only instead of making it available to the entire application.

Imported providers are easily replaced by providers from another imported NgModule. Such replacement might be by design but it could be unintentional and have adverse consequences.

There are two possible ways to restrict the scope of a service to a module only:

1. By using providedIn Property:

import { UserModule } from './UserModule.module';

@Injectable({
  providedIn: UserModule,
})
export class SomeService {
}

2. By declaring services in the providers array of Modules:

import { UserService } from '../user-service.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}

Q177. Can you share services using Modules in Angular?

Yes, you can but it is not recommended to share services by importing modules, you should import modules when you want to use directives, pipes, and components only.  

Actually, imported providers are easily replaced by providers from another imported NgModule. Such replacement might be by design but it could be unintentional and have adverse consequences.

When a root module is loaded at application launch, its @NgModule.providers have application-wide scope; so they are available for injection throughout the application.

As a general rule, import modules with providers exactly once, preferably in the application's root module. That's also usually the best place to configure, wrap, and override them.

The best approach to get a hold of shared services is through 'Angular dependency Injection' because importing a module will result in a new service instance.

Sharing Service using Module:

However, you can share services using modules in Angular. One way to do this is by using the forRoot() method. This method allows you to create a module with providers that can be shared across multiple modules.

First, create a module with the service you want to share. In the module, define a static forRoot() method that returns an object with two properties: ngModule and providers.

Here the ngModule property should be set to the module itself, and the providers property should be set to an array of providers that includes the service you want to share.

@NgModule({
  providers: [MyService]
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
  return {
    ngModule: SharedModule,
    providers: [MyService]
  };
  }
}

Now in the root module (usually AppModule), import the shared module using forRoot()

@NgModule({
  imports: [
  SharedModule.forRoot()
  ]
})
export class AppModule { }

In any other module that needs access to the shared service, import the shared module without calling forRoot().

@NgModule({
  imports: [
  SharedModule
  ]
})
export class AnotherModule { }

Q178. Why is the service provided in a feature module visible everywhere in the application?

Providers listed in the @NgModule of a bootstrapped module have application scope. So adding a service provider to @NgModule.providers effectively publishes the service to the entire application.

Now when anyone imports an NgModule, Angular adds the module's service providers to the application root injector. This makes the provider visible to every class in the application that knows the provider's lookup token, or name.

However, you can limit the scope of a provider to a specific module by declaring it using providedIn metadata option for a non-root NgModule. To limit access to a service, you can consider lazy loading the NgModule that provides that service. 

Q179. Why is the service provided in a lazy-loaded module visible only to that module?

Unlike the providers of the modules loaded at startup, providers of lazy-loaded modules are module-scoped. However, when you load a module lazily, Angular creates a new injector for that module and its children. This injector is a child of the application root injector. 

When the Angular router lazy-loads a module, it creates a new execution context. That context has its own injector, which is a direct child of the application injector. Therefore, if you declare a service provider at the module level using @NgModule.providers, it is effectively published only to that module and its children.

If you want to share a service across multiple lazy-loaded modules, you can create a shared module that provides the service and import it into each lazy-loaded module that needs it. Alternatively, you can use providedIn metadata option to limit the scope of a provider to a specific module or component.

Q180. Why does lazy loading always create a child injector?

Angular adds @NgModule.providers to the application root injector unless the NgModule is lazy-loaded. For a lazy-loaded NgModule, Angular creates a child injector and adds the module's providers to the child injector. So NgModule behaves differently depending on whether it's loaded during application start or lazy-loaded later. 

Why doesn't Angular add lazy-loaded providers to the application root injector as it does for eagerly loaded NgModules?

The Angular injector can add providers until it's first used. Once an injector starts creating and delivering services, its provider list is frozen; no new providers are allowed further.

When an application starts, Angular first configures the root injector with the providers of all eagerly loaded NgModules before creating its first component and injecting any of the provided services. Once the application begins, the application root injector is closed to new providers.

Now when an application logic triggers lazy loading of an NgModule. Angular must add the lazy-loaded module's providers to an injector somewhere. It can't add them to the application root injector because that injector is closed to new providers. So Angular creates a new child injector for the lazy-loaded module context.

Q181. How can you check and tell if a NgModule or service was previously loaded?

Some NgModules and their services should be loaded only once by the root AppModule. Importing the module a second time by lazy loading a module could produce adverse behavior that may be difficult to detect and diagnose.

To prevent this issue, you can write a constructor that attempts to inject the module or service from the root application injector. If the injection succeeds, the class has been loaded a second time. You can throw an error or take other remedial action.

Some NgModules, such as BrowserModule, implement such a guard. Here is a custom constructor for a NgModule called GreetingModule.

constructor(@Optional() @SkipSelf() parentModule?: GreetingModule) {
  if (parentModule) {
  throw new Error(
    'GreetingModule is already loaded. Import it in the AppModule only');
  }
}

Q182. What is the difference between the service() and factory() functions in Angular?

It is basically an AngularJS Interview Question. If you are new to AngularJS, then you might be confused between the service and factory as there is very little difference between them.

In AngularJS, both service() and factory() are used to create singletons that can be injected into other components like controllers, directives, and filters.  The main difference between the two is that service() is a constructor function, whereas factory() is not. 

Both service() and factory() can accomplish the same thing. However, in some cases, the factory gives you more flexibility to create an injectable with simpler syntax. in actuality, the factory() function is to design patterns that help in creating objects.

When you use service(), the function you write will be new. On the other hand, when you use factory(), the function (constructor) that you write will be invoked. 

For example, if you define a service called myService using service(), you can create an instance of it using new myService(). But if you define a factory called myFactory using factory(), you can create an instance of it using myFactory().



Recommended Articles




Thanks for visiting this page. Please follow and join us on  LinkedInFacebookTelegramQuoraYouTubeTwitterInstagramWhatsApp, VKTumbler, and Pinterest for regular updates.

No comments:

Post a Comment

Please do not enter any HTML. JavaScript or spam link in the comment box.