IT

서로 의존하는 서비스

itgroup 2023. 8. 31. 23:49
반응형

서로 의존하는 서비스

나의 Angular 2 앱에서, 나는 서로 의존하는 두 개의 서비스(서비스 A의 통화 방식과 그 반대)를 가지고 있습니다.

다음은 관련 코드입니다.

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'(정의되지 않음)에 대한 일부 매개 변수를 확인할 수 없습니다.모든 매개 변수가 Injector(주입기)로 표시되고 'Temp2Service'가 Injectable(주입기)로 표시되는지 확인합니다.

서비스 중 하나에서 생성자에 대해 설명하면 앱이 정상적으로 실행됩니다.그래서 제 생각에는 두 서비스의 "상호 참조"가 문제를 일으키고 있는 것 같습니다.

여기서 무슨 일이 일어나고 있는지 아십니까?아니면 제 접근법이 이미 잘못된 건가요?

이것은 순환 종속성이라고 불립니다.Angular2 자체에는 문제가 없습니다.제가 아는 어떤 언어로도 허용되지 않습니다.

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

단일 책임 원칙을 따른다면 순환 의존성 함정에 빠지지 않는다는 것입니다.

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

그것은 주입을 통해 분해될 수 있습니다.Injector그리고 다음과 같은 종속성을 요청합니다.

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

참고 항목원형 종속성 주입 각도 2

여기서 핵심은 생성자를 통해 서비스를 주입하는 것이 아니라 명시적인 세터와 게터를 사용하는 것입니다.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);

  }

}

서비스업

@Injectable()
export class FooService {

    barService: any;

    constructor(){
    }

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

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

}

저는 Angular > 4로 작업하기 위해 이 솔루션을 업데이트했습니다.인젝터 클래스를 사용하여 다른 서비스에 서비스를 주입할 수 있습니다.

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();
  }
}

그것은 순환 의존성이고 불행하게도 이것은 근본적인 컴퓨터 과학 문제, 즉 정보 문제입니다. 앵귤러가 해결할 수 없는 문제입니다.대신 다음과 같은 작업을 수행해 보십시오.

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

export class ServiceB {
 
 private a: ServiceA

 constructor(){
    
 }

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

}

그것이 아마도 그것을 하는 가장 좋은 방법일 것입니다.

우리는 이 문제를 해결하기 위해 forwordRef 함수를 해결할 수 있습니다.

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

@Inject(forwardRef(() => MyService) 개인 httpProxy: MyService

setTimeout 또는 injector 사용으로 순환 의존성 경고를 수정하고 injector에서 injector를 다른 함수로 이동하려고 했던 모든 것이 angular 7에서 작동하지 않았습니다.

제 작업 솔루션은 다음과 같습니다.

첫 번째 서비스에 대한 서비스 참조를 유지하기 위해 다른 서비스를 만들었습니다.

@Injectable()
export class AnotherService {

  private _service: AService;

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

그러면 다음과 같이 사용할 수 있습니다.

@Injectable()
export class AService {

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

그리고 여기:

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

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

Angular 2를 사용하고 있으며 일부 이벤트에서 서로의 호출 기능에 대한 순환 종속성이 필요한 경우 관찰 가능 항목을 사용하여 다른 서비스를 주입한 서비스에서 구독할 수 있습니다.

예:

@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]();
    });
  }
}

순환 의존성 문제에 부딪혔고, 많은 답을 찾았고, 그것을 해결하기 위한 최선의 방법은 다음과 같습니다.

제가 이해한 바로는, 당신이 합격하려고 할 때 문제가 발생합니다.a: A로.b: B 생성자로 이동합니다.따라서 이를 방지하는 방법은 객체를 생성한 다음 에만 설정하는 것입니다.

나 A와 B는 그렇게 독단적이지 않습니다, 나의 예는 있었던 나의 사례에 있을 것입니다.

가져오기는 순환 종속성 문제에 영향을 주지 않습니다.

토끼.구성요소.ts

export class RabbitComponent {

    public rabbitsArray: Rabbit[] = []

    constructor(){
        let lRabbit: Rabbit = new Rabbit(God.rabbitMotherFromEve())
        lRabbit.setRabbitComponent(this)
        rabbits.push(lRabbit)
    }
}

토끼.ts

export class Rabbit {
    public feetsArray: Foot[] // I know its not the best practices but more concise for example
    public rabbitComponent: RabbitComponent

    constructor (anyThingYouWantButRabbitComponent: RabbitMother){
    }
}

API를 쿼리하는 동안 문제가 발생했습니다.A많이 가질 수 있습니다Bs,B있습니다A부모.이러한 모델을 설정할 때 순환 종속성을 방지하려면 이러한 관계 중 하나를 생략해야 합니다.그런 다음 쿼리할 때 유형을 다음과 같이 캐스팅할 수 있습니다.any:

this.repositoryService.Query<A>(`$filter=Id eq ${B.AId}`).subscribe(As=>this.importantProp = (As[0] as any).C.property;)

그렇다면 A에 대한 정의는 다음과 같습니다.

@JsonProperty('B', [Object], true) Bs = new Array<Object>();
@JsonProperty('C', [Object], true) C = null;

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

귄터 답변 참조

Angular 2 및 System JS와의 원형 의존성

싱글톤이 허용되지 않는 경우 서비스 중 하나에서 NEW를 호출할 수 있습니다.

this._sessionService = new TempService(this);

두 서비스 모두 정의되지 않은 멤버 변수를 사용하지 않았기 때문에 이 방법을 선택했습니다.

언급URL : https://stackoverflow.com/questions/36378751/services-depending-on-each-other

반응형