当我们实际上可以在不使用装饰器的情况下注入服务时,为什么我们要使用 @Injectable() 装饰器呢?

Lea*_*123 5 dependency-injection decorator angular-services angular

我正在开发一个项目,遇到一个没有 @Injectable() 装饰器的服务,并且工作正常。到目前为止,我的印象是,在 Angular 中,如果我们想实现 DI,我们必须使用 @injectable() 装饰器并使用提供程序对其进行配置。使用提供者配置服务是强制性的,但使用 @injectable() 装饰器似乎不是强制性的。它仅在某些服务中使用。我注意到使用装饰器的服务和不使用装饰器的服务的唯一区别是前者本身有一些依赖项,而后者没有

我有两种类型的服务:

类型1:

   export class SharedService {
   //do something
   }
Run Code Online (Sandbox Code Playgroud)

类型2:

   @Injectable()
   export class MainCreditService {

     constructor(private http: Http, private config: Config) {
     this.config.EndPoints.subscribe(endpointObj =>  {
        this.environment = endpointObj;
    });
   }
Run Code Online (Sandbox Code Playgroud)

应用程序模块.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule, ReactiveFormsModule} from '@angular/forms';
import { HttpClientModule} from '@angular/common/http'

@NgModule({

declarations: [
AppComponent,
],

imports: [
BrowserModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
AppRoutingModule,
  ],

exports: [],
providers: [MainService,SharedService],
bootstrap: [AppComponent]
 })
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

应用程序组件.ts

import { Component } from '@angular/core';
import { HttpClient } from "@angular/common/http";

import { MainService } from '../../services/main.service';
import { SharedService } from '../../services/shared.service';
 
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
 })
export class AppComponent {

constructor(private mainservice: MainService, private sharedService: 
SharedService) { 
   //doSomething
 }
Run Code Online (Sandbox Code Playgroud)

为什么一个需要 @Injectable() 而另一个不需要

我看过一些关于 DI 的视频并浏览了一些文章,但仍然很难理解我们应该在哪里使用这个装饰器以及为什么。有人可以解释一下这个装饰器的目的,或者粘贴到已经解释得很好的来源的链接吗?

Gou*_*arg 11

是的,你说得对,我们可以在没有 Injectable() 装饰器的情况下创建服务。那我们为什么需要这个呢?

可注入装饰器或任何其他角度/自定义装饰器都会生成元数据。注入服务需要一种特殊类型的元数据(design:paramtypes)。

没有依赖项并且没有可注入:

@Component({
  selector: 'ponyracer-app',
  template: '<h1>PonyRacer</h1>'
})
export class PonyRacerAppComponent {
  constructor(private appService: AppService) {
    console.log(appService);
  }
}

// without Injectable 
export class AppService {
  constructor() {
    console.log('new app service');
  }
}
Run Code Online (Sandbox Code Playgroud)

这是 javascript 生成的组件和服务代码。您可以看到组件生成的代码和服务生成的代码之间存在一些差异。

当我们使用组件装饰器时,Angular 在这里添加了一些元数据。一种元数据是关于 appService 的。但服务代码没有元数据。

var AppService = (function () {
function AppService() {
  console.log('new app service');
}
return AppService;
}());
exports.AppService = AppService;

var PonyRacerAppComponent = (function() {
  function PonyRacerAppComponent(appService) {
    this.appService = appService;
    console.log(appService);
  }
  PonyRacerAppComponent = __decorate([
    core_1.Component({
      selector: 'ponyracer-app',
      template: '<h1>PonyRacer</h1>'
    }),
    __metadata('design:paramtypes', [app_service_1.AppService])
  ], PonyRacerAppComponent);
  return PonyRacerAppComponent;
}());
Run Code Online (Sandbox Code Playgroud)

那么,如果我们的服务依赖于其他服务(例如 HttpService),会发生什么情况呢?

export class AppService {
  constructor(http: HttpService) {
    console.log(http);
  }
}
Run Code Online (Sandbox Code Playgroud)

这是服务的生成代码:

var AppService = (function() {
  function AppService(http) {
    console.log(http);
  }
  return AppService;
}());
exports.AppService = AppService;
Run Code Online (Sandbox Code Playgroud)

Angular 不提供有关 http 变量的信息,当我们运行此代码时,它会给出类似错误:无法解析 AppService 的所有参数:(?) 的错误。

现在,如果此服务使用 Injectable() 装饰,或者即使任何自定义空装饰器,它将创建 http 服务元数据的引用。

var AppService = (function() {
  function AppService(http) {
    console.log(http);
  }
  AppService = __decorate([
    core_1.Injectable(),
    __metadata('design:paramtypes', [http_service_1.HttpService])
  ], AppService);
  return AppService;
}());
exports.AppService = AppService;
Run Code Online (Sandbox Code Playgroud)


小智 0

@Injectable()如果您通过使用provideInset to value来装饰服务root,它将在整个应用程序中创建单例实例,并在您注入的所有组件中使用相同的实例。例如:

class HomeComponent {
   constructor(private userService: UserService) {}
}
Run Code Online (Sandbox Code Playgroud)

请参考链接: https://angular.io/guide/dependency-injection#injector-hierarchy-and-service-instances