서로 의존하는 서비스
나의 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));
}
여기서 핵심은 생성자를 통해 서비스를 주입하는 것이 아니라 명시적인 세터와 게터를 사용하는 것입니다.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
많이 가질 수 있습니다B
s,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
'IT' 카테고리의 다른 글
전체 HTML 문서에 전역 글꼴을 적용하는 방법 (0) | 2023.08.31 |
---|---|
텍스트 길이에 따라 UITextView 높이를 동적으로 설정하는 방법은 무엇입니까? (0) | 2023.08.31 |
phonegap/httpova를 사용하는 동안 '노드'가 내부 또는 외부 명령, 작동 가능한 프로그램 또는 배치 파일로 인식되지 않습니다. (0) | 2023.08.31 |
투표 경쟁에서 부정행위자를 사냥하는 것 (0) | 2023.08.31 |
엔티티 관리자.setFlushMode() vs Query.setFlushMode() (0) | 2023.08.31 |