developer tip

서로에 따른 서비스

copycodes 2020. 12. 30. 08:18
반응형

서로에 따른 서비스


내 Angular 2 앱에는 서로 의존하는 두 가지 서비스가 있습니다 (서비스 A는 서비스 B에서 메서드를 호출하고 그 반대도 마찬가지).

관련 코드는 다음과 같습니다.

app.component.ts:

import {Component} from 'angular2/core';
import {TempService} from '../services/tmp';
import {Temp2Service} from '../services/tmp2';

@Component({
    selector: 'my-app',
    templateUrl: 'app/app/app.component.html',
    providers: [TempService, Temp2Service]
})
export class AppComponent { (...) }

서비스 1 :

import {Injectable} from 'angular2/core';
import {Temp2Service} from './tmp2';

@Injectable()
export class TempService {
  constructor (private _sessionService: Temp2Service) {}
}

서비스 2 :

import {Injectable} from 'angular2/core';
import {TempService} from './tmp';

@Injectable()
export class Temp2Service {
  constructor (private _sessionService: TempService) {}
}

앱을 실행하면 다음 오류가 발생합니다.

예외 : 'Temp2Service'(정의되지 않음)에 대한 모든 매개 변수를 확인할 수 없습니다. 모든 매개 변수가 Inject로 장식되어 있거나 유효한 유형 주석이 있고 'Temp2Service'가 Injectable로 장식되어 있는지 확인하십시오.

서비스 중 하나에서 생성자에 주석을 달면 앱이 정상적으로 실행됩니다. 그래서 내 생각 엔 두 서비스의 "상호 참조"가 문제를 일으키는 것입니다.

여기서 무엇이 잘못되고 있는지 알고 있습니까? 아니면 내 접근 방식이 이미 잘못 되었습니까?


이를 순환 종속성이라고합니다. Angular2 자체의 문제는 아닙니다. 내가 아는 어떤 언어로도 허용되지 않습니다.

이 순환 종속성을 제거하려면 코드를 리팩터링해야합니다. 이러한 서비스 중 하나를 새 서비스로 분리해야 할 가능성이 있습니다.

단일 책임 원칙을 따르면 순환 종속성 함정에 빠지지 않을 것입니다.


생성자 주입은 순환 종속성을 방지합니다.

Injector다음과 같이 명령 을 주입하고 종속성을 요청하여 분할 할 수 있습니다 .

private payrollService:PayrollService;
constructor(/*private payrollService:PayrollService*/ injector:Injector) {
  setTimeout(() => this.payrollService = injector.get(PayrollService));
}

참조 순환 의존성 삽입 각도 2


여기서 핵심은 생성자를 통해 서비스를 주입하는 것이 아니라 명시적인 setter 및 getter를 사용하는 것입니다. Angular 4에서 다음 패턴을 사용합니다.

app.component.ts

import { FooService } from './foo/foo.service';
import { BarService } from './bar/bar.service';

export class AppComponent {

  constructor(public fooService: FooService, public barService: BarService) {

    this.fooService.setBarService(barService);

  }

}

foo.service.ts

@Injectable()
export class FooService {

    barService: any;

    constructor(){
    }

    setBarService(barService: any): void {
        this.barService = barService;
    }

    getBarService(): any {
        return this.barService;
    }

}

순환 종속성에 대한 Angular 2 문서의 장이 있습니다. 매우 유용하다고 생각합니다.

의존성 주입


Angular> 4. Injector 클래스를 사용하여 다른 서비스에 서비스를 주입 할 수 있도록이 솔루션을 업데이트했습니다.

import { Injector } from '@angular/core';
import { TempService } from './tmp';


@Injectable()
export class Temp2Service {

  private tempService: any;

  constructor (private injector: Injector) { }

  public funcA() {
     this.tempService = this.injector.get(TempService);
     this.tempService.doSomething();
  }
}

순환 의존성이며 안타깝게도 Angular가 해결할 수없는 근본적인 컴퓨터 과학 문제 또는 정보 문제입니다. 대신 다음과 같이 시도하십시오.

export class ServiceA{
 constructor(private b: ServiceB){
    b.setA(this);
 }
}

export class ServiceB {

 private a: ServiceA

 constructor(){

 }

 setA(a){
   this.a = a;
 }

}

그게 최선의 방법 일 것입니다.


Angular 2를 사용하고 있고 일부 이벤트에서 서로의 함수를 호출하기 위해 순환 종속성이 필요한 경우 Observable을 사용하고 다른 서비스를 삽입 한 Service에서 구독 할 수 있습니다.

작은 예 :-

@Injectable()
class Service1{

observeEvents(){
return Obsevable.create((o)=>{
//store `o` it in any class variable
//whenever you want to call function of Service2 from this class, do this `o.next('method_name');`
});
}
}

@Injectable()
class Service2{
   constructor(private service1: Service1){
     this.service1.subscribe((method)=>{
        this[method]();
});
   }
}

이 문제를 해결하기 위해 forwordRef 함수를 풀 수 있습니다.

// 아직 정의되지 않은 참조를 참조 할 수 있습니다.

@Inject (forwardRef (() => MyService)) private httpProxy : MyService


인터페이스 사용-이것은 많은 언어에서 일반적인 패턴입니다.

Günters 답변보기

Circular dependency with Angular 2 and SystemJS


you can try to call NEW on one of the services if not having a singleton is acceptable. like

this._sessionService = new TempService(this);

This was the approach I took since neither service used undefined member variables.


Everything I tried to fix circular dependency warning with setTimeout or use of injector and moving the injection from constructor into another function didn't work for me with angular 7.

Here is my working solution:

I created another service just to hold the service referenz to first service:

@Injectable()
export class AnotherService {

  private _service: AService;

  get service(): AService {
    return this._service;
  }
  set service(service: AService) {
    this._service = service;
  }
}

Then I can use it like this:

@Injectable()
export class AService {

  constructor(private anotherService: AnotherService) {
    anotherService.service = this;
  }
  ...
}

and here:

@Injectable()
export class BService {
  private aService: AService;

  constructor(private injector: Injector) {
    const anotherService = injector.get(AnotherService);
    this.aService = anotherService.service;
  }
  ...
}

ReferenceURL : https://stackoverflow.com/questions/36378751/services-depending-on-each-other

반응형