programing

각도 2에서 싱글톤 서비스를 생성하려면 어떻게 해야 하는가?

prostudy 2022. 3. 20. 13:38
반응형

각도 2에서 싱글톤 서비스를 생성하려면 어떻게 해야 하는가?

부트스트래핑 시 주입은 모든 어린이가 동일한 인스턴스를 공유하도록 해야 한다고 읽었지만, 내 메인 및 헤더 구성요소(메인 앱에는 헤더 구성요소 및 라우터 아웃렛 포함)는 각각 별도의 서비스 인스턴스를 얻고 있다.

나는 페이스북 javascript api로 전화를 걸 때 사용하는 페이스북 서비스와 페이스북 서비스를 사용하는 사용자 서비스를 가지고 있다.여기 내 장식품이 있다.

bootstrap(MainAppComponent, [ROUTER_PROVIDERS, UserService, FacebookService]);

로깅을 보면 부트스트랩 호출이 완료된 것 같은데, 그러면 MainAppComponent, HeaderComponent 및 DefaultComponent의 코드가 실행되기 전에 FacebookService가 생성되는 것을 볼 수 있다.

여기에 이미지 설명을 입력하십시오.

업데이트(사각형 6 +)

싱글톤 서비스를 만드는 권장 방법이 바뀌었다.이제 에 명시하는 것이 좋다.@Injectable그것이 '뿌리'로 제공되어야 한다는 서비스에 대한 장식가.이것은 나에게 매우 이치에 맞으며 더 이상 당신의 모듈에서 제공되는 모든 서비스를 나열할 필요가 없다.필요할 때 서비스를 가져오기만 하면 적절한 장소에 등록이 된다.모듈을 가져온 경우에만 제공되도록 모듈을 지정할 수도 있다.

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

업데이트(사각형 2)

NgModule로 지금 하는 방법은 당신의 서비스 클래스가 들어 있는 'CoreModule'을 만들어 모듈의 제공자에 서비스를 나열하는 것이라고 생각한다.그런 다음 기본 앱 모듈의 핵심 모듈을 가져와 생성자에서 해당 클래스를 요청하는 모든 어린이에게 하나의 인스턴스를 제공하십시오.

코어모듈.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ApiService } from './api.service';

@NgModule({
    imports: [
        CommonModule
    ],
    exports: [ // components that we want to make available
    ],
    declarations: [ // components for use in THIS module
    ],
    providers: [ // singleton services
        ApiService,
    ]
})
export class CoreModule { }

AppModule.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';

@NgModule({
    declarations: [ AppComponent ],
    imports: [
        CommonModule,
        CoreModule // will provide ApiService
    ],
    providers: [],
    bootstrap: [ AppComponent ]
})
export class AppModule { }

오리지널

공급자를 나열하는 경우bootstrap()구성 요소 장식가에는 이러한 구성 요소를 나열할 필요가 없음:

import { ApiService } from '../core/api-service';

@Component({
    selector: 'main-app',
    templateUrl: '/views/main-app.html',
    // DO NOT LIST PROVIDERS HERE IF THEY ARE IN bootstrap()!
    // (unless you want a new instance)
    //providers: [ApiService]
})
export class MainAppComponent {
    constructor(private api: ApiService) {}
}

실제로 '공급자'에 클래스를 나열하면 새로운 인스턴스가 생성되고, 부모 구성요소가 이미 클래스를 나열한 경우 아이들은 그럴 필요가 없으며, 그렇게 하면 새로운 인스턴스가 생성된다.

제이슨이 전적으로 옳아!의존성 주사가 작용하는 방식 때문에 생긴 겁니다.계층형 인젝터를 기반으로 한 겁니다.

Angle2 응용 프로그램에는 다음과 같은 여러 인젝터가 있다.

  • 응용프로그램을 부트스트래핑할 때 구성하는 루트
  • 구성 요소당 인젝터.다른 구성 요소를 다른 구성 요소 내에서 구성 요소를 사용하십시오.구성 요소 인젝터는 상위 구성 요소 1의 하위 항목이다.응용 프로그램 구성 요소(응용 프로그램을 부스트할 때 지정하는 구성 요소)는 루트 인젝터를 상위 인젝터로 한다.

각도2가 구성 요소 생성자에 무언가를 주입하려고 할 때:

  • 구성 요소와 관련된 인젝터를 조사한다.일치하는 항목이 있으면 해당 인스턴스를 가져오는 데 사용할 것이다.이 인스턴스는 느리게 생성되며 이 인젝터를 위한 싱글톤이다.
  • 이 레벨에 공급자가 없을 경우 상위 인젝터 등을 살펴보게 된다.

따라서 전체 용도에 대해 싱글톤을 사용하려면 공급자가 루트 인젝터 또는 애플리케이션 구성 요소 인젝터 수준에서 정의되어야 한다.

그러나 Angul2는 밑에서 인젝터 트리를 볼 것이다.이는 최저 수준의 제공자가 사용되며 관련 인스턴스의 범위가 이 수준이 된다는 것을 의미한다.

자세한 내용은 이 질문을 참조하십시오.

나는 각도가 티에리가 말한 것처럼 계층적 주입기를 가지고 있다는 것을 안다.

하지만 부모에게 주입하고 싶지 않은 사용 사례를 찾을 경우를 대비해서 다른 선택사항이 있어

우리는 서비스의 인스턴스를 생성하여 항상 그것을 반환함으로써 그것을 달성할 수 있다.

import { provide, Injectable } from '@angular/core';
import { Http } from '@angular/core'; //Dummy example of dependencies

@Injectable()
export class YourService {
  private static instance: YourService = null;

  // Return the instance of the service
  public static getInstance(http: Http): YourService {
    if (YourService.instance === null) {
       YourService.instance = new YourService(http);
    }
    return YourService.instance;
  }

  constructor(private http: Http) {}
}

export const YOUR_SERVICE_PROVIDER = [
  provide(YourService, {
    deps: [Http],
    useFactory: (http: Http): YourService => {
      return YourService.getInstance(http);
    }
  })
];

그런 다음 구성 요소에서 사용자 정의 제공 방법을 사용하십시오.

@Component({
  providers: [YOUR_SERVICE_PROVIDER]
})

그리고 계층형 인젝터에 의존하지 않고 싱글톤 서비스를 해야 한다.

나는 이것이 더 나은 방법이라고 말하는 것이 아니다. 누군가 계층적 주입기가 불가능할 경우에 대비해서 말이다.

구문이 변경되었다.링크를 확인하십시오.

의존성은 인젝터의 범위 내에서 단골격이다.아래 예에서 HeroService 인스턴스는 HeroesComponent와 HeroListComponent 자식 간에 공유된다.

Step 1. @Injectable decorator로 싱글톤 클래스 만들기

@Injectable()
export class HeroService {
  getHeroes() { return HEROES;  }
}

2단계. 시공사 주입

export class HeroListComponent { 
  constructor(heroService: HeroService) {
    this.heroes = heroService.getHeroes();
  }

3단계. 제공자 등록

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    routing,
    HttpModule,
    JsonpModule
  ],
  declarations: [
    AppComponent,
    HeroesComponent,
    routedComponents
  ],
  providers: [
    HeroService
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule { }

이것은 나에게 잘 작용하는 것 같다.

@Injectable()
export class MyStaticService {
  static instance: MyStaticService;

  constructor() {
    return MyStaticService.instance = MyStaticService.instance || this;
  }
}

추가@Injectable서비스의 실내 장식가, 그리고 루트 모듈에 제공자로 등록하면 싱글톤이 된다.

다음은 Angul 버전 2.3의 작업 예시 입니다.서비스의 생성자를 이 생성자(프라이빗 userService:UserService) (UserService) 그리고 그것은 앱을 위한 싱글톤을 만들 것이다.

user.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { Subject }    from 'rxjs/Subject';
import { User } from '../object/user';


@Injectable()
export class UserService {
    private userChangedSource;
    public observableEvents;
    loggedUser:User;

    constructor() {
       this.userChangedSource = new Subject<any>();
       this.observableEvents = this.userChangedSource.asObservable();
    }

    userLoggedIn(user:User) {
        this.loggedUser = user;
        this.userChangedSource.next(user);
    }

    ...
}

app.component.ts

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { UserService } from '../service/user.service';
import { User } from '../object/user';

@Component({
    selector: 'myApp',
    templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
    loggedUser:User;

    constructor(private _userService:UserService) { 
        this._userService.observableEvents.subscribe(user => {
                this.loggedUser = user;
                console.log("event triggered");
        });
    }
    ...
}

사용할 수 있다useValue제공자로

import { MyService } from './my.service';

@NgModule({
...
  providers: [ { provide: MyService, useValue: new MyService() } ],
...
})

에서는 Angul@6을 수 providedIn의 한 곳에.Injectable.

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

}

여기서 문서를 확인하십시오.

Angle에서는 서비스를 싱글톤으로 만드는 두 가지 방법이 있다.

  1. 서비스가 애플리케이션 루트에 제공되어야 한다고 선언한다.
  2. AppModule 또는 AppModule에서만 가져오는 모듈에 서비스를 포함하십시오.

Angul 6.0부터 싱글톤 서비스를 만드는 선호되는 방법은 애플리케이션 루트에 제공해야 하는 서비스를 명시하는 것이다.이 작업은 제공된 설정에 의해 수행됨서비스의 @Injective decorator를 루트화하려면:

app.module.ts에서만 서비스를 제공자로 선언하십시오.

그것이 나를 위해 그 일을 해 주었다.

providers: [Topic1Service,Topic2Service,...,TopicNService],

그런 다음 생성자 개인 매개변수를 사용하여 다음을 삽입하십시오.

constructor(private topicService: TopicService) { }

또는 서비스가 html에서 사용되는 경우 -prod 옵션이 다음과 같이 클레임할 것이다.

Property 'topicService' is private and only accessible within class 'SomeComponent'.

서비스 멤버를 추가하고 생성자에서 받은 인스턴스로 입력하십시오.

export class SomeComponent {
  topicService: TopicService;
  constructor(private topicService: TopicService) { 
    this.topicService= topicService;
  }
}

A singleton service앱에 하나의 인스턴스만 존재하는 서비스.

애플리케이션을 위한 싱글톤 서비스를 제공하는 방법이 (2) 있다.

  1. 를 이용하다providedIn재산, 또는

  2. 모듈을 에 직접 제공하십시오.AppModule

제공된 사용

Angul 6.0부터 싱글톤 서비스를 만드는 가장 좋은 방법은providedIn그 서비스에 뿌리를 박다@Injectable()】가 이는 애플리케이션 루트에 서비스를 제공하도록 Angle에게 알려준다.

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

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

NgModule 공급자 배열

6.0 이전 Angular 버전으로 구축된 앱에서 서비스는 다음과 같이 NgModule 제공자 어레이로 등록된다.

@NgModule({
  ...
  providers: [UserService],
  ...
})

만약 이것이NgModule근본이 되었다.AppModuleUserService는 싱글톤이며 앱 전체에서 사용할 수 있다.이렇게 코딩되어 있는 것을 볼 수 있지만providedIn@Injectable()서비스 자체에 대한 장식자는 당신의 서비스를 나무처럼 흔들리게 만들기 때문에 Angular 6.0보다 선호된다.

  1. 애플리케이션 수준에서 서비스를 싱글톤으로 만들려면 app.module.ts에서 정의하십시오.

    제공자: [ MyApplicationService ] (하위 모듈에서도 동일하게 정의하여 해당 모듈을 특정화할 수 있음)

    • 싱글톤 개념을 깨는 해당 구성 요소의 인스턴스를 생성하는 제공자에 이 서비스를 추가하지 말고 생성자를 통해 주입하십시오.
  2. 구성 요소 수준에서 싱글톤 서비스를 정의하려면 app.module.ts에 해당 서비스를 추가하고 아래 스니펫과 같이 특정 구성 요소 내의 제공자 배열에 추가하십시오.

    @Component({ selector: 'app-root', templateUrl: './test.component.html', styleUrls: []/test.component.scss'], 제공자 : [TestMyService]}}}

  3. 각도 6은 애플리케이션 수준에서 서비스를 추가할 수 있는 새로운 방법을 제공한다.AppModule의 제공자[] 어레이에 서비스 클래스를 추가하는 대신 @Injectable()에서 다음 구성을 설정하십시오.

    @Injectable({proved)In: 'root'} 내보내기 클래스 MyService { ...}

하지만 "새로운 구문"은 한가지 장점을 제공한다: 서비스는 각도에 의해 느리게 로드될 수 있고, 중복 코드는 자동으로 제거될 수 있다.이는 일반적으로 더 큰 서비스와 앱에만 적용되지만 더 나은 성능과 로딩 속도로 이어질 수 있다.

위의 훌륭한 대답 외에도, 만약 당신의 싱글톤에 있는 것들이 여전히 싱글톤으로 동작하지 않는다면, 무언가 빠진 것이 있을지도 모른다.싱글톤에서 공공기능을 호출하고 잘못된 변수를 사용하고 있다는 것을 발견했을 때 나는 그 문제에 부딪쳤다.알고 보니 문제는 바로 이겁니다.this싱글톤의 어떤 공공기능에 대해서도 싱글톤에 속박될 수 없다는 것을 보장받지 못한다.이는 다음과 같이 여기의 조언에 따라 수정될 수 있다.

@Injectable({
  providedIn: 'root',
})
export class SubscriptableService {
  public serviceRequested: Subject<ServiceArgs>;
  public onServiceRequested$: Observable<ServiceArgs>;

  constructor() {
    this.serviceRequested = new Subject<ServiceArgs>();
    this.onServiceRequested$ = this.serviceRequested.asObservable();

    // save context so the singleton pattern is respected
    this.requestService = this.requestService.bind(this);
  }

  public requestService(arg: ServiceArgs) {
    this.serviceRequested.next(arg);
  }
}

또는 단순히 클래스 멤버를 다음과 같이 선언할 수 있다.public static대신에public그러면 문맥은 문제가 되지 않겠지만, 당신은 그들처럼 접근해야 할 것이다.SubscriptableService.onServiceRequested$종속성 주입을 사용하고 이를 통해 액세스하는 대신this.subscriptableService.onServiceRequested$.

상위 및 하위 서비스

나는 부모 서비스와 그 자녀가 다른 사례를 사용하는 것에 어려움을 겪고 있었다.하나의 인스턴스를 강제로 사용하려면 앱 모듈 공급자의 하위 항목을 참조하여 상위 항목을 별칭으로 지정하십시오.부모가 자녀의 재산에 접근할 수는 없지만 두 서비스 모두에 동일한 인스턴스가 사용될 것이다.https://angular.io/guide/dependency-injection-providers#aliased-class-providers

app.cs.ts

providers: [
  ChildService,
  // Alias ParentService w/ reference to ChildService
  { provide: ParentService, useExisting: ChildService}
]

앱 모듈 범위를 벗어난 구성 요소에서 사용하는 서비스

컴포넌트와 서비스로 구성된 라이브러리를 만들 때 두 개의 인스턴스가 만들어지는 문제에 부딪쳤다.하나는 나의 Angul 프로젝트, 하나는 내 도서관 내부의 컴포넌트.해결 방법:

my-component.ts.

@Component({...})
export class MyOutsideComponent {
  @Input() serviceInstance: MyOutsideService;
  ...
}

my-component.ts.

  constructor(public myService: MyOutsideService) { }

my-component.component.propertl

<app-my-outside [serviceInstance]="myService"></app-my-outside>

음, 각도 서비스 범위는 루트 모듈, 게으르게 로드된 모듈 또는 구성 요소 수준에서 서비스를 제공하는 위치에 따라 달라진다.

여기 그것을 실제 사례로 아름답게 묘사하는 비디오가 있다.

https://youtu.be/aDyqnQrer3o

참조URL: https://stackoverflow.com/questions/36198785/how-do-i-create-a-singleton-service-in-angular-2

반응형